Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
5818d6a
fix(core): three correctness fixes, plus policy metadata passthrough
refeed Aug 1, 2026
ba5b58a
feat(platform): add `tirith platform check`
refeed Aug 3, 2026
d24ac62
fix(platform): scrub HCL literals from configuration
refeed Aug 3, 2026
3b8fcd9
fix(platform): mask sensitive_attributes paths, and name the state do…
refeed Aug 3, 2026
43490ff
fix(platform): rank approval-required above warned
refeed Aug 3, 2026
18cb6c3
feat(platform): region key, document discovery, and the shared upload…
refeed Aug 4, 2026
c9bc8c5
feat(platform): record the source repo, and clean up the archive afte…
refeed Aug 5, 2026
cbc397c
fix(platform): do not send an unset folder on the upload URL
refeed Aug 5, 2026
d627143
refactor: rename the terraform action policy-only -> tirith-check
refeed Aug 5, 2026
041d5f9
fix(platform): rebuild planned_values so costing and Checkov work, an…
refeed Aug 5, 2026
9d0cc81
fix(report): render Checkov findings, which came out as an empty block
refeed Aug 5, 2026
7a9ba2a
docs(roadmap): reflect what shipped, and correct three claims that ar…
refeed Aug 5, 2026
1a7f6c7
feat(platform): retain the project archive for the autofix system
refeed Aug 5, 2026
bc55f12
feat(platform): publish the masked state as the workflow's tfstate.json
refeed Aug 5, 2026
b514635
feat(platform): never lose the policy gate to an oversized archive
refeed Aug 5, 2026
5de1fe6
feat(report): say which commit the findings describe
refeed Aug 6, 2026
b758b52
chore: drop files this branch never meant to carry, and format
refeed Aug 6, 2026
1c0ea9f
refactor(platform): name the action, and carry the archive in a conte…
refeed Aug 6, 2026
7ea3132
docs: name the mode consistently after the rename
refeed Aug 6, 2026
3254658
refactor(platform): send the archive as a run field; approvals warn, …
refeed Aug 6, 2026
d0ed11c
style: satisfy pydocstyle in the platform client
refeed Aug 7, 2026
a47f63a
fix(platform): close three masking leaks and three ways a verdict wen…
refeed Aug 7, 2026
df57513
fix(platform): only fail on unreadable facts when nothing answered
refeed Aug 7, 2026
31c6277
fix(platform): close the --plan-file half of the archive leak, and na…
refeed Aug 7, 2026
3561460
refactor(platform): stop sending policyInputKind
refeed Aug 7, 2026
2dbd2b0
fix(platform): mask a show -json state, which shipped in plaintext
refeed Aug 7, 2026
afcaf44
refactor(platform): run the policy step as a pre-plan step, not a ter…
refeed Aug 10, 2026
288a5b6
refactor(platform): fix the policy step template, dropping --step-tem…
refeed Aug 10, 2026
ad27edb
docs(platform): --step-template-id overrides the policy step, not ter…
refeed Aug 10, 2026
4e2f807
docs(platform): name the archive field terraformProjectZip
refeed Aug 10, 2026
86df010
feat(platform): deliver the bundle through the artifacts volume, not …
refeed Aug 10, 2026
9c8605a
feat(platform): name the bundle per commit, sent per run
refeed Aug 10, 2026
a48f61a
docs(platform): the upload key is informational, not load-bearing
refeed Aug 11, 2026
eeaf998
refactor(platform): name the run stage tirith-iac-governance
refeed Aug 11, 2026
1b8eba0
fix(platform): mask secrets in provider-computed mirrors too
refeed Aug 11, 2026
38d163b
chore: drop unrelated scratch files this branch swept in
refeed Aug 11, 2026
a53d53f
feat(platform): tell the step whether the workflow manages its state
refeed Aug 11, 2026
87e4258
fix(platform): suppress the VCS checkout per run, keep it on the work…
refeed Aug 11, 2026
33b6828
fix(platform): hide the bundles behind __sg., and render a finding wi…
refeed Aug 11, 2026
d6aaa5d
Revert the __sg. bundle prefix
refeed Aug 11, 2026
eb72613
docs: document platform check and exit codes, and stop the generated …
refeed Aug 11, 2026
a0c878e
Update platform-check.md
refeed Aug 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,47 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).




## [1.2.0] - 2026-08-03

### Added
- `tirith platform check`: run an organization's policies against a plan, state or arbitrary JSON
document from CI or a laptop. Masks the document locally, packs it with the terraform source into
an archive, uploads it, creates a StackGuardian run, polls it and reports the verdict as JSON
and/or markdown.
- `ExitStatus.ERROR_POLICY_FAILED` (3), so a caller can tell "a policy said no" from "tirith could
not reach the platform". Exit 1 stays reserved for the latter, and applies even without
`--fail-on-error`: a run that produced no verdict must never look like a pass.

### Changed
- `cli.main(args=...)` is now honoured. It previously called `parse_args()` with no argument, so
the parameter was ignored and the CLI could only ever read `sys.argv`.

### Notes
- The local evaluation surface is unchanged, including its single-dash long options. Subcommands
are dispatched before the flat parser sees anything, so `--json` output stays byte-identical.
- No new runtime dependencies: the platform integration is stdlib-only.

## [1.1.0] - 2026-08-01

### Added
- `core`: Policy metadata passthrough — `meta.id`, `meta.name`, `meta.description`,
`meta.severity`, `meta.enforcement`, `meta.tags` and `meta.remediation` now reach the result
document when a policy declares them. Keys that are absent are omitted, so the output of a
policy declaring none of them is unchanged. `{{ var.x }}` substitution works in all of them.

### Fixed
- `core`: Variable substitution no longer mutates the caller's policy dictionary. Evaluating the
same parsed policy more than once (a policy set, or a retry) previously leaked substituted
values from one evaluation into the next.
- `core`: An unsupported `condition.type` now populates `result` instead of returning without it,
which raised `KeyError` in the pretty printer far from the real cause.
- `core`: Provider errors reported without a `ProviderError` severity are now surfaced instead of
being discarded and `None` evaluated against the condition — a typo'd `operation_type` read as
a genuine policy violation. These are treated as malformed provider calls and are deliberately
not subject to `error_tolerance`.

## [1.0.5] - 2025-11-19

### Fixed
Expand Down
93 changes: 84 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg)](code_of_conduct.md)
[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg)](CODE_OF_CONDUCT.md)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=StackGuardian_policy-framework&metric=alert_status&token=4a4d06e73940505edb7fc9d27a7f03b35fbbf23d)](https://sonarcloud.io/summary/new_code?id=StackGuardian_policy-framework)
[![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=StackGuardian_policy-framework&metric=sqale_rating&token=4a4d06e73940505edb7fc9d27a7f03b35fbbf23d)](https://sonarcloud.io/summary/new_code?id=StackGuardian_policy-framework)
Expand Down Expand Up @@ -26,6 +26,8 @@ Tirith scans declarative Infrastructure as Code (IaC) configurations like Terraf
- [Features](#features)
- [Installation](#installation)
- [Usage](#usage)
- [Exit codes](#exit-codes)
- [Evaluating against your StackGuardian organization](#evaluating-against-your-stackguardian-organization)
- [Example Tirith policies](#example-tirith-policies)
- [Terraform Plan](#terraform-plan-provider)
- [Infracost](#infracost-provider)
Expand Down Expand Up @@ -89,8 +91,8 @@ pip install git+https://github.com/StackGuardian/tirith.git
- Clone the repository to your local machine:

```bash
git clone <repository-url>
cd <repository-folder>
git clone https://github.com/StackGuardian/tirith.git
cd tirith
```

- Start the Docker Engine using docker desktop or CLI.
Expand Down Expand Up @@ -143,43 +145,107 @@ pip install -e .

```
tirith --version
1.0.0-beta.12

tirith 1.2.0
```

Congratulations! Tirith has been setup in your system

## Usage

```
usage: tirith [-h] [-policy-path PATH] [-input-path PATH] [--json] [--verbose] [--version]
usage: tirith [-h] [-policy-path PATH] [-input-path PATH] [-var-path PATH]
[-var PATH] [--json] [--verbose] [--version]

Tirith (StackGuardian Policy Framework)

options:
-h, --help show this help message and exit
-policy-path PATH Path containing Tirith policy as code
-input-path PATH Input file path
-var-path PATH Variable file path(s)
-var PATH Inline variable(s)
--json Only print the result in JSON form (useful for passing output to other programs)
--verbose Show detailed logs of from the run
--version show program's version number and exit

Subcommands:

tirith platform check --help Evaluate against the policies your StackGuardian
organization enforces, rather than local files.

About Tirith:

* Abstract away the implementation complexity of policy engine underneath.
* Simplify creation of declarative policies that are easy to read and interpret.
* Provide a standard framework for scanning various configurations with granularity.
* Provide modularity to enable easy extensibility
* Github - https://github.com/StackGuardian/tirith
* Docs - https://docs.stackguardian.io/docs/tirith/overview
* Docs - https://github.com/StackGuardian/tirith#readme
```


## Exit codes

| Code | Meaning |
|---|---|
| 0 | Policies passed, or nothing was in scope to gate on |
| 1 | Tirith could not complete the evaluation — bad input, unreachable API, engine error |
| 2 | Timed out waiting for a StackGuardian run |
| 3 | A policy failed. Only from `platform check --fail-on-error` |
| 130 | Interrupted |

**3 is deliberately not 1.** `3` means your infrastructure violates a policy; `1` means Tirith could
not tell you either way. A CI job that treats every non-zero code the same reports an outage as a
policy violation, and — worse — cannot distinguish a real gate from a broken one.

Note the legacy top-level form (`tirith -policy-path … -input-path …`) always exits `0`, pass or
fail, so on its own it does not gate anything. Use `platform check`, or the
[GitHub Action](https://github.com/StackGuardian/tirith-iac-governance-action), when you need the
exit code to mean something.

## Evaluating against your StackGuardian organization

`tirith platform check` evaluates against the policies your StackGuardian organization enforces,
instead of policy files committed to your repository — so policy lives in one place rather than being
copied into every repository that needs gating.

```
export SG_API_TOKEN=sgo_... # an organization token
export SG_ORG=my-org

tirith platform check --workflow-id my-repo --input-path plan.json --fail-on-error
```

It masks the document on your machine before anything leaves it, packs it with your terraform source,
uploads it, runs the policies on StackGuardian, and prints the verdict. `--input-path` is optional
when a `plan.json` or `tfplan.json` is in the working directory.

Common flags:

| | |
|---|---|
| `--region {eu,us}` | Which StackGuardian region. Default `eu`, or `$SG_REGION` |
| `--api-key -` | Read the key from stdin instead of the environment |
| `--plan-file tfplan` | A binary plan, rendered through `terraform show -json` in memory |
| `--state-path` / `--infracost-path` | Add a state document or a cost breakdown to the evaluation |
| `--source-dir ""` | Do not upload the terraform source |
| `--fail-on-error` | Exit `3` when a policy fails, instead of `0` |
| `--output-json` / `--output-markdown` | Write the verdict to files for a later CI step |

`--api-url` overrides `--region` for a self-hosted or dedicated host. Every flag is in
[docs/platform-check.md](docs/platform-check.md) or `tirith platform check --help`.

Running this from GitHub Actions? Use the action instead — it wires up the plan discovery, the sticky
pull-request comment, the check run and the exit codes for you:
[StackGuardian/tirith-iac-governance-action](https://github.com/StackGuardian/tirith-iac-governance-action).

## Example Tirith policies

[Examples using various providers](tests/providers)

### Terraform plan provider
<details>
<summary>Terraform plan provider — example policies and output</summary>

#### Example 1:
VPC and EC2 instance policy
Expand Down Expand Up @@ -311,7 +377,7 @@ Policy:
}
}
],
"eval_expression": "check1 && check11 && check111 & check2 & check22"
"eval_expression": "check1 && check22"
}

```
Expand Down Expand Up @@ -489,14 +555,15 @@ JSON Output:
}
],
"errors": [],
"eval_expression": "check1 && check11 && check111 & check2 & check22"
"eval_expression": "check1 && check22"
}

```
</details>

### Infracost Provider
<details>
<summary>Infracost Provider — example policies and output</summary>

Cost control policy

Expand Down Expand Up @@ -648,6 +715,7 @@ JSON Output:

### StackGuardian Workflow Policy (using SG workflow provider)
<details>
<summary>StackGuardian Workflow Policy (using SG workflow provider) — example policies and output</summary>
- Terraform Workflow should require an approval to create or destroy resources

```json
Expand Down Expand Up @@ -800,6 +868,7 @@ JSON Output:

### JSON
<details>
<summary>JSON — example policies and output</summary>
Example Policy

```json
Expand Down Expand Up @@ -1000,6 +1069,7 @@ JSON Output

### Kubernetes
<details>
<summary>Kubernetes — example policies and output</summary>

Kubernetes (using Kubernetes provider)
#### Example 1
Expand Down Expand Up @@ -1299,6 +1369,11 @@ Wanna submit a feedback? It's as simple as writing and posting it in the <a href

## Support

Open an [issue](https://github.com/StackGuardian/tirith/issues) for a bug or a question about policy
authoring. For anything specific to a StackGuardian organization — enforcement scope, a run that
errored, an API key — contact StackGuardian support instead, since that needs account context this
repository has no access to.

## License

<i>Apache License 2.0</i>
Expand Down
Loading
Loading