A deterministic check that a protected operation is reachable from an entry point without a check dominating the path, per framework, built on the existing obligations checker, caller index and entry mapper; scored as a rule arm on the access-control training pool. Follows the maintainer's finding that the hunter's features describe shape and cannot decide unsafety. Co-Authored-By: Claude Fable 5.1 <[email protected]>
4.8 KiB
Implementation Plan
-
1. Paths from the caller index
-
1.1 Add
PathRecordandcompose_pathsinsrc/openultrasast/semantic/obligations/paths.py(P)- Upward walk through a
callers(path, function)callable, depth and fan-out bounds, stop at the first entry, chains kept per file, deduplicated; unreached targets returned - Done when
tests/test_obligation_paths.pycovers depth 1 to 3, unreached, fan-out cut and same-name files, andcheck_obligationsaccepts the records aspaths(one test runs the checker with them) - Requirements: 3.1, 3.2, 3.3, 3.4, 3.5, 3.6
- Boundary: obligations.paths
- Upward walk through a
-
2. Entry recognisers
-
2.1 Stapler and Jetty recognisers in
mapping.py(P)- Public
do[A-Z]...methods on exposed types or with Stapler-typed or@QueryParameterparameters; JettyAbstractHandler,HttpServlet, JAX-RS resources; evidence strings;publiconly forUnprotectedRootAction - Done when
tests/test_mapping_frameworks.pynames the entries of a fixture Descriptor, rejects a private helper nameddoX, and the existing mapping tests still pass - Requirements: 1.1, 1.6, 1.7, 1.8
- Boundary: mapping
- Public
-
2.2 Symfony, Livewire and Laravel controller, Remix export and Tornado recognisers in
mapping.py(P)- Done when fixture files of each shape yield
routeentries with evidence and the negative fixtures yield none - Requirements: 1.2, 1.3, 1.4, 1.5, 1.7, 1.8
- Boundary: mapping
- Done when fixture files of each shape yield
-
3. Enforcement witnesses and facts
-
3.1
semantic/obligations/enforcement.pyproducing router and decoratorDischargewitnesses (P)- Laravel route middleware and controller
middleware/authorizeResource; SymfonyIsGranted,Security, security.yamlaccess_control; Tornadoauthenticated; names listed in the facts headers - Done when
tests/test_obligation_enforcement.pyshows a guarded Laravel route, a Symfony attribute and a Tornado decorator each produce one witness thatOrderDominanceaccepts for the handler's operation - Requirements: 2.1, 2.2, 2.5, 2.6
- Boundary: obligations.enforcement
- Laravel route middleware and controller
-
3.2 Operation and discharger rows for the pool's shapes in
ruleset/obligations/{java,php,python,typescript}.toml(P)- Java: credential lookups and outbound connection tests in
doTestConnection-style handlers, item reads and writes,checkPermission/checkAnyPermissionas path guards,hasPermissionas ownership check; Remix: session requirements as path guards, record reads by request id as protected reads needingownership_check; Tornado: handleropen/getas entries needingpath_guard; Jetty service start as privileged action. Every name checked in the clones or documentation, said in the header - Done when
tests/test_obligation_facts.pyloads the files and one operation and one discharger per language resolve - Requirements: 2.3, 2.4, 2.7
- Boundary: ruleset/obligations
- Java: credential lookups and outbound connection tests in
-
4. The prover
-
4.1
hunt/prover.py:prove_changeover the hunterContext,Coverage, findings as hunt defects- Touched functions from head lines, build output left out, targets include direct callees holding operations, IRs of hop files passed to the checker, extra witnesses from enforcement, coverage counts by reason, no model
- Done when
tests/test_hunt_prover.pyshows: an unguarded Stapler handler callinglookupCredentialsgives one finding with entry, hops and missingpath_guard; acheckPermissionabove the call gives none; a guarded Laravel route gives none; an unrecognised framework gives coverage only; the finding dict haspath,line,family,function,evidence,id - Requirements: 4.1, 4.2, 4.3, 4.4, 4.5, 4.6, 6.2, 7.1, 8.1, 8.2
- Depends: 1.1, 2.1, 3.1, 3.2
-
5. The arm
-
5.1
benchmarks/valid/prover_arm.py: run over a pool slice with checkpoints, summarise with the valid metrics- Record envelope copied from
hunter_arm; instrument fields; resume;summary.jsonwith recall (pushes and locations, Wilson), false alarms per 100, precision, instrument failures, seconds per change and the list over 120 s, per-repository and per-framework coverage,uncoveredrepositories; refuse on zero-byte reads - Done when
tests/test_prover_arm.pyruns a two-change fixture pool end to end and the summary carries every field above; a record with zero bytes read makessummarizerefuse - Requirements: 5.1, 5.2, 5.3, 5.4, 5.5, 6.1, 7.2
- Depends: 4.1
- Record envelope copied from
-
6. Measurement (maintainer, not Codex)
-
6.1 Run the arm on
benchmarks/valid/train/pool-train.tomlover the training clones; writebenchmarks/measurements/<date>-access-control-prover/with NOTES, summary, coverage table; compare with the DSPy and hunter arms of the same pool- Requirements: 5.2, 5.3, 7.2