use std::fs;
use tempfile::tempdir;
use zift::cli::ScanArgs;
use zift::config::ZiftConfig;
use zift::rules;
use zift::scanner;
#[test]
fn enforcement_points_increments_when_call_routes_through_policy_import() {
let dir = tempdir().unwrap();
fs::write(
dir.path().join("orders.ts"),
r#"import { authorize } from '../lib/authz';
export function listOrders(user: User) {
if (authorize("orders:read")) {
return db.orders.find();
}
return null;
}
"#,
)
.unwrap();
let config = ZiftConfig::default();
let loaded_rules = rules::load_rules(None, &config).expect("embedded rules load");
let args = ScanArgs {
path: dir.path().to_path_buf(),
..ScanArgs::default()
};
let result = scanner::scan(dir.path(), &loaded_rules, &args, &config).unwrap();
assert_eq!(
result.enforcement_points,
1,
"expected the policy-imported authorize() call to count as an enforcement point; \
got {} (findings: {:?})",
result.enforcement_points,
result
.findings
.iter()
.map(|f| (f.pattern_rule.clone(), f.line_start))
.collect::<Vec<_>>(),
);
assert!(
!result
.findings
.iter()
.any(|f| f.pattern_rule.as_deref() == Some("ts-authorize-function-call")),
"policy-routed call leaked into findings: {:?}",
result.findings,
);
}
#[test]
fn enforcement_points_is_zero_without_policy_imports() {
let dir = tempdir().unwrap();
fs::write(
dir.path().join("orders.ts"),
r#"import { authorize } from '../lib/utils';
export function listOrders(user: User) {
if (authorize("orders:read")) {
return db.orders.find();
}
return null;
}
"#,
)
.unwrap();
let config = ZiftConfig::default();
let loaded_rules = rules::load_rules(None, &config).expect("embedded rules load");
let args = ScanArgs {
path: dir.path().to_path_buf(),
..ScanArgs::default()
};
let result = scanner::scan(dir.path(), &loaded_rules, &args, &config).unwrap();
assert_eq!(result.enforcement_points, 0);
assert!(
result
.findings
.iter()
.any(|f| f.pattern_rule.as_deref() == Some("ts-authorize-function-call")),
"structural rule should have fired without the policy-import shortcut; \
got: {:?}",
result
.findings
.iter()
.map(|f| f.pattern_rule.clone())
.collect::<Vec<_>>(),
);
}
fn scan_fixture(filename: &str, contents: &str) -> zift::scanner::ScanResult {
let dir = tempdir().unwrap();
fs::write(dir.path().join(filename), contents).unwrap();
let config = ZiftConfig::default();
let loaded_rules = rules::load_rules(None, &config).expect("embedded rules load");
let args = ScanArgs {
path: dir.path().to_path_buf(),
..ScanArgs::default()
};
zift::scanner::scan(dir.path(), &loaded_rules, &args, &config).unwrap()
}
#[test]
fn enforcement_points_increments_for_go_opa_import() {
let result = scan_fixture(
"decide.go",
r#"package main
import (
"fmt"
"github.com/open-policy-agent/opa/rego"
)
func decide() {
_ = rego.New(rego.Query("data.authz.allow"))
fmt.Println("decided")
}
"#,
);
assert_eq!(
result.enforcement_points,
1,
"expected the OPA rego.New() call to count as an enforcement point; \
got {} (findings: {:?})",
result.enforcement_points,
result
.findings
.iter()
.map(|f| (f.pattern_rule.clone(), f.line_start))
.collect::<Vec<_>>(),
);
assert!(
!result
.findings
.iter()
.any(|f| f.pattern_rule.as_deref() == Some("go-opa-rego-eval")),
"policy-routed call leaked into findings: {:?}",
result.findings,
);
}
#[test]
fn go_policy_propagation_does_not_suppress_unrelated_paired_assignment() {
let result = scan_fixture(
"mixed.go",
r#"package main
import "github.com/example/authz"
func check() {
factory, RequirePermission := authz.NewAccess, func(string) bool { return true }
_ = factory
if RequirePermission("orders:read") {
return
}
}
"#,
);
assert_eq!(
result.enforcement_points,
0,
"unrelated second assignment target should not be counted as externalized; findings: {:?}",
result
.findings
.iter()
.map(|f| (f.pattern_rule.clone(), f.line_start))
.collect::<Vec<_>>(),
);
assert!(
result
.findings
.iter()
.any(|f| f.pattern_rule.as_deref() == Some("go-permission-check-call")),
"local RequirePermission call should remain an embedded finding; got: {:?}",
result
.findings
.iter()
.map(|f| (f.pattern_rule.clone(), f.line_start))
.collect::<Vec<_>>(),
);
}
#[test]
fn go_package_propagation_reroutes_cross_file_consumer() {
let dir = tempdir().unwrap();
let pkg_dir = dir.path().join("internal").join("database");
fs::create_dir_all(&pkg_dir).unwrap();
fs::write(
pkg_dir.join("database.go"),
r#"package database
import "github.com/example/authz"
type Database struct {
accessFactory func() any
}
func New() *Database {
return &Database{accessFactory: authz.NewAccess}
}
"#,
)
.unwrap();
fs::write(
pkg_dir.join("bundle_status.go"),
r#"package database
func (d *Database) checkBundle() {
_ = d.accessFactory().WithPrincipal("bob").WithResource("bundles")
}
"#,
)
.unwrap();
let config = ZiftConfig::default();
let loaded_rules = rules::load_rules(None, &config).expect("embedded rules load");
let args = ScanArgs {
path: dir.path().to_path_buf(),
..ScanArgs::default()
};
let result = scanner::scan(dir.path(), &loaded_rules, &args, &config).unwrap();
assert!(
result.enforcement_points >= 1,
"expected the consumer's d.accessFactory().WithPrincipal(...) chain to \
count as an enforcement point via cross-file propagation; got {} (findings: {:?})",
result.enforcement_points,
result
.findings
.iter()
.map(|f| (
f.pattern_rule.clone(),
f.file.display().to_string(),
f.line_start
))
.collect::<Vec<_>>(),
);
assert!(
!result
.findings
.iter()
.any(|f| f.file.ends_with("bundle_status.go")
&& f.pattern_rule.as_deref() == Some("go-access-descriptor-builder")),
"consumer file leaked an embedded finding — package-scoped propagation \
should have rerouted the call: {:?}",
result
.findings
.iter()
.map(|f| (
f.pattern_rule.clone(),
f.file.display().to_string(),
f.line_start
))
.collect::<Vec<_>>(),
);
}
#[test]
fn enforcement_points_increments_for_python_authz_import() {
let result = scan_fixture(
"views.py",
r#"from authz import check_orders_permission
def list_orders(user):
check_orders_permission(user)
return db.orders.find()
"#,
);
assert!(
result.enforcement_points >= 1,
"expected the Python check_permission() call to count as an enforcement point; \
got {} (findings: {:?})",
result.enforcement_points,
result
.findings
.iter()
.map(|f| (f.pattern_rule.clone(), f.line_start))
.collect::<Vec<_>>(),
);
}
#[test]
fn enforcement_points_increments_for_java_authz_import() {
let result = scan_fixture(
"OrderService.java",
r#"package com.example;
import com.example.policy.Authorize;
public class OrderService {
public boolean list(User user) {
return Authorize.hasRole("admin");
}
}
"#,
);
assert!(
result.enforcement_points >= 1,
"expected the Java Authorize.check() call to count as an enforcement point; \
got {} (findings: {:?})",
result.enforcement_points,
result
.findings
.iter()
.map(|f| (f.pattern_rule.clone(), f.line_start))
.collect::<Vec<_>>(),
);
}
#[test]
fn enforcement_points_increments_for_csharp_policy_di() {
let result = scan_fixture(
"OrderController.cs",
r#"using Authz = Company.Policy.Authorizer;
public class OrderController {
private readonly Authz _authz;
public OrderController(Authz authz) {
_authz = authz;
}
public async Task<IActionResult> List(User user, Document document) {
var result = await _authz.AuthorizeAsync(user, document, "CanReadOrders");
if (!result.Succeeded) {
return Forbid();
}
return Ok();
}
}
"#,
);
assert!(
result.enforcement_points >= 1,
"expected the C# policy DI AuthorizeAsync call to count as an enforcement point; \
got {} (findings: {:?})",
result.enforcement_points,
result
.findings
.iter()
.map(|f| (f.pattern_rule.clone(), f.line_start))
.collect::<Vec<_>>(),
);
assert!(
!result
.findings
.iter()
.any(|f| f.pattern_rule.as_deref()
== Some("csharp-authorization-service-authorize-async")),
"policy-routed C# call leaked into findings: {:?}",
result.findings,
);
}
#[test]
fn in_package_policy_implementation_file_is_skipped() {
let dir = tempdir().unwrap();
let policy_dir = dir.path().join("internal").join("authz");
fs::create_dir_all(&policy_dir).unwrap();
fs::write(
policy_dir.join("authz_test.go"),
r#"package authz
func TestNewAccess(t *testing.T) {
a := NewAccess()
_ = a.WithPrincipal("bob").WithResource("doc").Allow()
}
"#,
)
.unwrap();
let config = ZiftConfig::default();
let loaded_rules = rules::load_rules(None, &config).expect("embedded rules load");
let args = ScanArgs {
path: dir.path().to_path_buf(),
..ScanArgs::default()
};
let result = scanner::scan(dir.path(), &loaded_rules, &args, &config).unwrap();
assert!(
result.findings.is_empty(),
"in-package policy implementation file leaked findings: {:?}",
result
.findings
.iter()
.map(|f| (f.pattern_rule.clone(), f.line_start))
.collect::<Vec<_>>(),
);
assert_eq!(
result.enforcement_points, 0,
"in-package policy implementation file should not be counted as an enforcement point",
);
}
#[test]
fn externalized_rules_count_without_policy_import_shortcut() {
let cases = [
(
"handler.js",
r#"
async function decide(client, params) {
return avp.isAuthorizedWithToken(params);
}
"#,
"ts-aws-verified-permissions",
),
(
"views.py",
r#"
def decide(client, params):
return avp.is_authorized(**params)
"#,
"py-aws-verified-permissions",
),
(
"decide.go",
r#"package main
func decide(ps *PolicySet, req Request) {
ok, diag := ps.IsAuthorized(req)
_, _ = ok, diag
}
"#,
"go-cedar-eval",
),
(
"Handler.cs",
r#"
public async Task<bool> Decide(Client avp, Request request) {
var response = await avp.IsAuthorizedAsync(request);
return response.Decision == Decision.Allow;
}
"#,
"csharp-aws-verified-permissions",
),
];
for (filename, contents, rule_id) in cases {
let result = scan_fixture(filename, contents);
assert_eq!(
result.enforcement_points, 1,
"expected {rule_id} in {filename} to count as an externalized enforcement point; \
got {} (findings: {:?})",
result.enforcement_points, result.findings,
);
assert!(
!result
.findings
.iter()
.any(|f| f.pattern_rule.as_deref() == Some(rule_id)),
"externalized rule {rule_id} leaked into embedded findings: {:?}",
result.findings,
);
}
}