A security finding usually describes one condition at one location: a broad IAM action, an unpinned workflow dependency, a public ingress rule, or a hard-coded cryptographic algorithm. That is necessary evidence. It does not show whether the condition is reachable, what authority crosses it, or which durable effect it enables.
A static security exposure graph connects findings to repository-defined identities, credentials, policies, resources, data, and effects. The graph should not replace findings. It should make their relationships explicit and preserve the evidence behind every edge.
Findings answer local questions
SARIF can represent normalized results with rules, locations, code flows, invocation details, and relationships. OASIS SARIF 2.1.0 That makes it a useful interchange format for scanner evidence.
A finding still has a deliberately local scope. For example:
- workflow requests an OIDC token;
- role trust accepts a repository subject;
- role permits
iam:PassRole; - compute definition references a runtime role;
- runtime role can read a secret;
- workload has network reach to a datastore.
Reported separately, those facts produce six tickets. Connected, they describe a possible authority path from repository modification to sensitive data.
Edges need evidence, not intuition
Represent each node and edge with type and provenance:
| Element | Example evidence |
|---|---|
| Workflow | File path, revision, trigger, permissions block |
| Federated subject | OIDC issuer, audience, and subject condition |
| Role | Terraform resource or CloudFormation logical ID |
| Permission | Policy statement, action, resource, condition |
| Resource | Repository declaration and stable identifier |
| Network reach | Security-group, route, listener, and protocol evidence |
| Effect | Documented API semantics and resource sensitivity |
An edge may mean “references,” “can assume,” “can pass,” “permits action on,” “routes to,” or “encrypts with.” Do not use a generic related_to edge where the security decision depends on direction or semantics.
Authorization illustrates why composition matters
AWS evaluates identity policies together with applicable resource, session, boundary, and organization policies. AWS IAM policy evaluation logic A finding against one policy document cannot by itself calculate the effective result.
An evidence graph can retain each policy as a node and connect it to the principal, request context, and resource it constrains. Unknown or runtime-only context should remain an explicit unknown edge—not be filled with an optimistic assumption.
Worked example: repository to production effect
Consider this static path:
modifiable workflow → GitHub OIDC subject → deploy role → PassRole → task role → secret read → production datastore
The high-value review questions are not “how many findings exist?” They are:
- Can an untrusted contributor change the workflow or a dependency it invokes?
- Does role trust bind the intended repository, workflow context, branch, or environment?
- Which runtime roles can the deploy session pass?
- What can the selected runtime role access?
- Does the deployed workload have network and application reach to the target?
- Which single controls interrupt the most material paths?
This creates prioritization based on reachable effect and shared control points. Fixing one trust condition or pass-role boundary may cut several paths; closing one low-impact isolated finding may cut none.
Separate observed, inferred, and unknown edges
A defensible graph uses evidence states:
- Observed: directly parsed from a versioned repository artifact.
- Derived: produced by a deterministic rule whose inputs are retained.
- Inferred: plausible relationship requiring verification.
- Runtime-required: cannot be established from the repository alone.
- Unknown: required evidence was absent, unsupported, or failed analysis.
BaitaPhish's deeper Research develops capability, authority, reach, trajectory, and cut-set reasoning. BaitaPhish capability, authority, and reach Research The repository graph is one static evidence plane within that broader model, not a claim to reproduce runtime truth.
Graph quality depends on coverage
An exposure graph can create stronger-looking false assurance if it hides what was not parsed. Every graph build should report repository revision, supported artifact types, included and excluded paths, parser failures, unresolved references, external dependencies, and runtime-only edges.
The graph should degrade to “unknown” when evidence is missing. It should never infer “safe” from absence of a node that the parser was unable to discover.
Practical takeaway
Keep scanner findings as immutable, inspectable evidence. Add typed relationships only where their direction and source can be explained. Then prioritize material paths and high-leverage cuts while keeping deployment and runtime unknowns visible.
Continue with Capability, Authority, and Reach for the deeper graph model and Threat Modeling as Testable Control Claims for evidence-driven verification.
Limitations
Static graphs cannot establish deployed state, active sessions, data sensitivity, vulnerability exploitability, or actual attacker behavior without additional evidence. This Article describes an analysis model. It does not claim that RepoNavi or BaitaPhish currently implements repository exposure-graph generation.