<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: TrustFix</title>
    <description>The latest articles on DEV Community by TrustFix (@trustfix).</description>
    <link>https://dev.to/trustfix</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3856749%2F1fc438c3-e273-4f2f-849b-90fc38d1e473.png</url>
      <title>DEV Community: TrustFix</title>
      <link>https://dev.to/trustfix</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/trustfix"/>
    <language>en</language>
    <item>
      <title>January 2026 AWS Condition Keys: What Changed and Why It Matters</title>
      <dc:creator>TrustFix</dc:creator>
      <pubDate>Thu, 09 Apr 2026 15:00:00 +0000</pubDate>
      <link>https://dev.to/trustfix/january-2026-aws-condition-keys-what-changed-and-why-it-matters-5142</link>
      <guid>https://dev.to/trustfix/january-2026-aws-condition-keys-what-changed-and-why-it-matters-5142</guid>
      <description>&lt;p&gt;In January 2026, AWS added new condition context keys for GitHub Actions OIDC trust policies. This was a quiet update — no blog post, no re:Invent announcement — but it fundamentally changes how you should write trust policies for GitHub Actions federation.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem: mutable identifiers
&lt;/h2&gt;

&lt;p&gt;Before January 2026, the standard way to restrict an OIDC trust policy to a specific GitHub repository was to use the &lt;code&gt;sub&lt;/code&gt; claim with the repository name:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Condition"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"StringEquals"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"token.actions.githubusercontent.com:sub"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"repo:my-org/my-repo:ref:refs/heads/main"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The problem: &lt;code&gt;my-org/my-repo&lt;/code&gt; is a &lt;strong&gt;mutable identifier&lt;/strong&gt;. If someone renames the repository, transfers it to another organization, or deletes and recreates it with the same name, the trust policy still matches. The identity the policy was written for no longer exists, but something with the same name does.&lt;/p&gt;

&lt;p&gt;This isn't theoretical. GitHub repository transfers happen routinely during acquisitions, reorganizations, and open-source project migrations.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fix: immutable condition keys
&lt;/h2&gt;

&lt;p&gt;AWS now supports these condition context keys for GitHub's OIDC provider:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;repository_id&lt;/code&gt;&lt;/strong&gt; — The immutable numeric ID of the repository. Survives renames and transfers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;actor_id&lt;/code&gt;&lt;/strong&gt; — The immutable numeric ID of the GitHub user who triggered the workflow.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;repository_owner_id&lt;/code&gt;&lt;/strong&gt; — The immutable numeric ID of the organization or user who owns the repository.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;runner_environment&lt;/code&gt;&lt;/strong&gt; — Whether the workflow is running on GitHub-hosted or self-hosted runners.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are part of the OIDC token claims that GitHub sends to AWS. They've always been in the token — AWS just didn't allow you to use them in trust policy conditions until January 2026.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to update your trust policies
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Before (mutable):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;condition&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;test&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"StringEquals"&lt;/span&gt;
  &lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"token.actions.githubusercontent.com:sub"&lt;/span&gt;
  &lt;span class="nx"&gt;values&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"repo:my-org/my-repo:ref:refs/heads/main"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;After (immutable):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;condition&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;test&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"StringEquals"&lt;/span&gt;
  &lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"token.actions.githubusercontent.com:sub"&lt;/span&gt;
  &lt;span class="nx"&gt;values&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"repo:my-org/my-repo:environment:production"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;condition&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;test&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"StringEquals"&lt;/span&gt;
  &lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"token.actions.githubusercontent.com:repository_id"&lt;/span&gt;
  &lt;span class="nx"&gt;values&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"123456789"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;condition&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;test&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"StringEquals"&lt;/span&gt;
  &lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"token.actions.githubusercontent.com:repository_owner_id"&lt;/span&gt;
  &lt;span class="nx"&gt;values&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"987654321"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;repository_id&lt;/code&gt; is a belt-and-suspenders approach alongside the &lt;code&gt;sub&lt;/code&gt; claim. Even if the repository name changes, the immutable ID check will either still match (same repo, renamed) or fail (different repo with the same name).&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding your repository_id
&lt;/h2&gt;

&lt;p&gt;Your repository's immutable ID is available via the GitHub API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; https://api.github.com/repos/my-org/my-repo | jq .id
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or in any GitHub Actions workflow, it's available as &lt;code&gt;github.repository_id&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What our scan found
&lt;/h2&gt;

&lt;p&gt;In our 10,000-repo scan, we analyzed how repositories reference their identity in OIDC trust policies. The vast majority still use mutable repository names. Adoption of the January 2026 immutable keys is near zero in public repositories — the feature is too new and there's been minimal documentation from AWS about the change.&lt;/p&gt;

&lt;p&gt;This creates a temporal window: teams that adopt these keys now have a meaningful security advantage over those who haven't heard about the update.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to do today
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Add &lt;code&gt;repository_id&lt;/code&gt; conditions to all OIDC trust policies alongside your existing &lt;code&gt;sub&lt;/code&gt; conditions&lt;/li&gt;
&lt;li&gt;Add &lt;code&gt;repository_owner_id&lt;/code&gt; to prevent cross-organization confusion&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;StringEquals&lt;/code&gt; (not &lt;code&gt;StringLike&lt;/code&gt;) for all condition comparisons&lt;/li&gt;
&lt;li&gt;Add an &lt;code&gt;environment&lt;/code&gt; condition for production-critical roles&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;TrustFix detects trust policies that are missing immutable condition keys and generates the Terraform fix automatically. Try it at &lt;a href="https://trustfix.dev" rel="noopener noreferrer"&gt;trustfix.dev&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;The condition keys referenced in this post are documented in &lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_iam-condition-keys.html" rel="noopener noreferrer"&gt;AWS's OIDC federation documentation&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://trustfix.dev/blog/static-credentials-2026" rel="noopener noreferrer"&gt;trustfix.dev&lt;/a&gt;. TrustFix is a non-human identity security platform that detects trust policy misconfigurations and auto-generates validated Terraform fixes. Free CLI: &lt;code&gt;npx oidc-audit scan&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>security</category>
      <category>github</category>
      <category>cloud</category>
    </item>
    <item>
      <title>Checkov's OIDC Bug: Why CKV_AWS_358 Misses 80% of Misconfigurations</title>
      <dc:creator>TrustFix</dc:creator>
      <pubDate>Tue, 07 Apr 2026 15:00:00 +0000</pubDate>
      <link>https://dev.to/trustfix/checkovs-oidc-bug-why-ckvaws358-misses-80-of-misconfigurations-4mb</link>
      <guid>https://dev.to/trustfix/checkovs-oidc-bug-why-ckvaws358-misses-80-of-misconfigurations-4mb</guid>
      <description>&lt;p&gt;If you're using Checkov to audit your AWS IAM OIDC trust policies, you might assume you're covered. Checkov is an excellent general-purpose infrastructure-as-code scanner with hundreds of built-in checks — it's one of the best tools in the IaC security space and I use it myself. But OIDC trust policies are a specialized domain, and Checkov's coverage there has a gap.&lt;/p&gt;

&lt;p&gt;It's not. Checkov has exactly one OIDC-related check — CKV_AWS_358 — and it has a confirmed bug that causes false positives on non-OIDC roles.&lt;/p&gt;

&lt;h2&gt;
  
  
  The bug: sts:AssumeRole vs sts:AssumeRoleWithWebIdentity
&lt;/h2&gt;

&lt;p&gt;CKV_AWS_358 is supposed to detect IAM roles that allow OIDC federation without proper condition restrictions. The check looks for trust policies that permit assuming the role via web identity federation.&lt;/p&gt;

&lt;p&gt;The problem is on &lt;a href="https://github.com/bridgecrewio/checkov/issues/6983" rel="noopener noreferrer"&gt;line 65 of the check&lt;/a&gt;: it searches for &lt;code&gt;sts:AssumeRole&lt;/code&gt; in the trust policy action field. But OIDC federation uses &lt;code&gt;sts:AssumeRoleWithWebIdentity&lt;/code&gt; — a different IAM action.&lt;/p&gt;

&lt;p&gt;Because &lt;code&gt;sts:AssumeRole&lt;/code&gt; is a substring of &lt;code&gt;sts:AssumeRoleWithWebIdentity&lt;/code&gt;, the check matches both. This means any role that allows cross-account assume role (a completely normal pattern that has nothing to do with OIDC) gets flagged as an OIDC misconfiguration.&lt;/p&gt;

&lt;p&gt;The result: noisy false positives that teach teams to ignore the check entirely.&lt;/p&gt;

&lt;p&gt;This is the kind of subtle issue that's easy to miss in a scanner with 1,000+ checks — it doesn't reflect on Checkov's overall quality, just on the difficulty of getting OIDC-specific detection right.&lt;/p&gt;

&lt;h2&gt;
  
  
  Even without the bug: 1 check out of 10 patterns
&lt;/h2&gt;

&lt;p&gt;Let's assume the bug gets fixed. CKV_AWS_358 checks for one thing: whether an OIDC trust policy has conditions restricting which identities can assume the role.&lt;/p&gt;

&lt;p&gt;That's one misconfiguration pattern out of at least ten that matter:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;#&lt;/th&gt;
&lt;th&gt;Misconfiguration&lt;/th&gt;
&lt;th&gt;CKV_AWS_358&lt;/th&gt;
&lt;th&gt;TrustFix&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Missing sub condition&lt;/td&gt;
&lt;td&gt;Partial (buggy)&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Overly broad trust (StringLike wildcards)&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Missing audience condition&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Fork PR risk (hardcoded ARN + PR trigger)&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Wildcard environment&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;Expired OIDC provider&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;Overprivileged role permissions&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;Overprivileged admin role&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;AI agent overprivileged role&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;AI agent missing scope condition&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Patterns 2 through 10 are invisible to Checkov.&lt;/p&gt;

&lt;h2&gt;
  
  
  1 of 5 OIDC providers
&lt;/h2&gt;

&lt;p&gt;CKV_AWS_358 checks for GitHub's OIDC provider (&lt;code&gt;token.actions.githubusercontent.com&lt;/code&gt;). But AWS IAM supports OIDC federation with at least five major CI/CD providers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Actions&lt;/strong&gt; — token.actions.githubusercontent.com&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitLab CI&lt;/strong&gt; — gitlab.com&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Terraform Cloud&lt;/strong&gt; — app.terraform.io&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CircleCI&lt;/strong&gt; — oidc.circleci.com&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Buildkite&lt;/strong&gt; — agent.buildkite.com&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Checkov only checks GitHub. If your organization uses GitLab CI with AWS OIDC federation and has a misconfigured trust policy, Checkov will never flag it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trivy: zero OIDC checks
&lt;/h2&gt;

&lt;p&gt;For completeness: Trivy, another widely-used security scanner, has zero AWS OIDC trust policy checks as of April 2026. It's excellent for container image scanning and Kubernetes misconfiguration detection, but OIDC trust policies are outside its current scope.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fix generation gap
&lt;/h2&gt;

&lt;p&gt;Even if Checkov's detection were comprehensive, it stops at detection. It tells you something is wrong but doesn't tell you exactly how to fix it.&lt;/p&gt;

&lt;p&gt;For OIDC trust policies, the fix is nuanced. You need to know:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which condition key to use (sub vs repository_id vs actor_id)&lt;/li&gt;
&lt;li&gt;Whether to use StringEquals or StringLike&lt;/li&gt;
&lt;li&gt;What the correct condition value format is for your specific repository and branch&lt;/li&gt;
&lt;li&gt;Whether to add an environment condition&lt;/li&gt;
&lt;li&gt;How to handle the January 2026 immutable condition keys&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;TrustFix generates the exact Terraform code for the fix, validated through six layers of analysis, and opens it as a PR with a Confidence Score.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this means
&lt;/h2&gt;

&lt;p&gt;If OIDC trust policy security is important to your organization (and given that 743 repos are critically vulnerable per our 10,000-repo scan, it should be), don't rely on a single buggy check in a general-purpose scanner.&lt;/p&gt;

&lt;p&gt;Dedicated tooling exists. &lt;a href="https://trustfix.dev" rel="noopener noreferrer"&gt;TrustFix&lt;/a&gt; covers all 10 patterns across multiple OIDC providers and generates validated fixes. Free tier available — 1 AWS account, unlimited scanning.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Disclosure: I built TrustFix. The Checkov bug referenced here is publicly documented in &lt;a href="https://github.com/bridgecrewio/checkov/issues/6983" rel="noopener noreferrer"&gt;GitHub issue #6983&lt;/a&gt;. I have immense respect for the Bridgecrew/Palo Alto team and the open-source security community. This post is about a gap in OIDC-specific coverage, not a critique of Checkov's broader capabilities.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://trustfix.dev/blog/static-credentials-2026" rel="noopener noreferrer"&gt;trustfix.dev&lt;/a&gt;. TrustFix is a non-human identity security platform that detects trust policy misconfigurations and auto-generates validated Terraform fixes. Free CLI: &lt;code&gt;npx oidc-audit scan&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>security</category>
      <category>terraform</category>
      <category>opensource</category>
    </item>
    <item>
      <title>80% of GitHub Repos Still Use Static AWS Credentials in 2026</title>
      <dc:creator>TrustFix</dc:creator>
      <pubDate>Sun, 05 Apr 2026 15:00:00 +0000</pubDate>
      <link>https://dev.to/trustfix/80-of-github-repos-still-use-static-aws-credentials-in-2026-2odb</link>
      <guid>https://dev.to/trustfix/80-of-github-repos-still-use-static-aws-credentials-in-2026-2odb</guid>
      <description>&lt;p&gt;We scanned 10,000 public GitHub repositories and analyzed 54,767 GitHub Actions workflows that interact with AWS. The goal was simple: understand how the industry is handling the transition from static AWS credentials to OIDC-based authentication in CI/CD pipelines.&lt;/p&gt;

&lt;p&gt;The results are worse than we expected.&lt;/p&gt;

&lt;h2&gt;
  
  
  The headline numbers
&lt;/h2&gt;

&lt;p&gt;Out of 54,767 workflows analyzed across 10,000 repositories:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;80.7% still use static AWS credentials&lt;/strong&gt; (AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY stored as GitHub Secrets)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;19.2% have adopted OIDC&lt;/strong&gt; federation via &lt;code&gt;configure-aws-credentials&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;7.6% have hardcoded IAM role ARNs&lt;/strong&gt; directly in public workflow files&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Only 13.9% use GitHub environment protection&lt;/strong&gt; rules&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;743 repositories are critically vulnerable&lt;/strong&gt; — they have hardcoded role ARNs AND accept &lt;code&gt;pull_request&lt;/code&gt; triggers, making them exploitable via fork-based OIDC token theft&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To put that in context: if you open a pull request against any of those 743 repos, the workflow runs with the base repository's OIDC trust — potentially giving you access to their AWS account.&lt;/p&gt;

&lt;h2&gt;
  
  
  OIDC adoption is growing, but slowly
&lt;/h2&gt;

&lt;p&gt;GitHub Actions added OIDC support in late 2021. AWS followed with &lt;code&gt;configure-aws-credentials&lt;/code&gt; v2. The security benefits are clear: no long-lived secrets, automatic credential rotation, and fine-grained trust policies tied to specific repositories and branches.&lt;/p&gt;

&lt;p&gt;Despite being available for over four years, OIDC adoption across the repositories we scanned sits at roughly a third. The remaining two-thirds rely on static credentials that, if leaked, provide persistent access until manually rotated. Based on workflow creation dates and commit timestamps in our dataset, adoption has been accelerating — but not fast enough.&lt;/p&gt;

&lt;h2&gt;
  
  
  The CRITICAL finding: 743 repos vulnerable to fork-based token theft
&lt;/h2&gt;

&lt;p&gt;This is the most concerning pattern we found. When a repository:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Uses OIDC for AWS authentication&lt;/li&gt;
&lt;li&gt;Has the role ARN hardcoded in a public workflow file&lt;/li&gt;
&lt;li&gt;Accepts &lt;code&gt;pull_request&lt;/code&gt; as a workflow trigger&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;...then anyone who forks the repo and opens a PR can potentially trigger a workflow that assumes the target's AWS IAM role. The attacker doesn't need the role ARN to be secret — it's right there in the YAML file.&lt;/p&gt;

&lt;p&gt;Named repositories in this CRITICAL category include workflow files from &lt;strong&gt;pytorch/pytorch&lt;/strong&gt;, &lt;strong&gt;botpress/botpress&lt;/strong&gt;, &lt;strong&gt;redpanda-data/redpanda&lt;/strong&gt;, &lt;strong&gt;great-expectations/great_expectations&lt;/strong&gt;, &lt;strong&gt;aws/karpenter-provider-aws&lt;/strong&gt;, &lt;strong&gt;h2oai/h2o-llmstudio&lt;/strong&gt;, &lt;strong&gt;webiny/webiny-js&lt;/strong&gt;, &lt;strong&gt;cloudquery/cloudquery&lt;/strong&gt;, and &lt;strong&gt;supabase/supabase&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Yes, you read that correctly. &lt;strong&gt;AWS's own karpenter-provider-aws repository&lt;/strong&gt; has a workflow in this pattern.&lt;/p&gt;

&lt;p&gt;A note on responsible disclosure: All data in this report comes from publicly accessible GitHub repositories analyzed via the GitHub API. We follow responsible disclosure practices and standard 90-day timelines. Organizations mentioned above can contact &lt;a href="mailto:security@trustfix.dev"&gt;security@trustfix.dev&lt;/a&gt; to discuss findings, request additional details, or be excluded from future publications. Our goal is to improve the ecosystem, not to shame individual projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  How role ARNs are exposed
&lt;/h2&gt;

&lt;p&gt;We categorized how repositories reference their AWS role ARNs:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;% of Workflows&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Not visible (secrets/OIDC)&lt;/td&gt;
&lt;td&gt;80.1%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GitHub Secrets reference&lt;/td&gt;
&lt;td&gt;9.5%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hardcoded in YAML&lt;/td&gt;
&lt;td&gt;7.6%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Environment variable&lt;/td&gt;
&lt;td&gt;2.8%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The 7.6% with hardcoded ARNs — that's 4,163 workflows across thousands of repositories with their AWS account ID and IAM role name sitting in plain text in a public GitHub repository. Combined with a &lt;code&gt;pull_request&lt;/code&gt; trigger, this is an open door.&lt;/p&gt;

&lt;h2&gt;
  
  
  Environment protection: the forgotten control
&lt;/h2&gt;

&lt;p&gt;GitHub Environments provide a critical security boundary: they require approval before a workflow can access environment secrets, and they restrict the OIDC &lt;code&gt;sub&lt;/code&gt; claim to specific branches. This means even if someone opens a malicious PR, the workflow can't assume a role that requires the &lt;code&gt;production&lt;/code&gt; environment unless an approver explicitly allows it.&lt;/p&gt;

&lt;p&gt;Only &lt;strong&gt;13.9%&lt;/strong&gt; of the workflows we scanned reference a GitHub environment. The other 86.1% have no approval gate between a pull request and AWS credential access.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this means for your team
&lt;/h2&gt;

&lt;p&gt;If you're using GitHub Actions with AWS, here's what to check:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you're still on static credentials:&lt;/strong&gt; You're in the 80.7% majority, but that's not a good place to be. Every secret stored in GitHub is a credential that can be leaked via workflow logs, compromised actions, or repository access changes. Migrate to OIDC — it takes about 15 minutes per repository.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you've adopted OIDC:&lt;/strong&gt; Good start, but check your trust policy conditions. Use &lt;code&gt;StringEquals&lt;/code&gt; (not &lt;code&gt;StringLike&lt;/code&gt;) for the &lt;code&gt;sub&lt;/code&gt; claim. Scope to specific repos AND branches. Use the immutable &lt;code&gt;repository_id&lt;/code&gt; condition key that AWS added in January 2026 instead of the mutable repository name. Add an &lt;code&gt;environment&lt;/code&gt; condition.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you have hardcoded role ARNs:&lt;/strong&gt; Move them to GitHub Secrets immediately. A hardcoded ARN in a public workflow file tells an attacker exactly which AWS account and role to target.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you use &lt;code&gt;pull_request&lt;/code&gt; triggers with OIDC:&lt;/strong&gt; This is the most dangerous combination. Switch to &lt;code&gt;pull_request_target&lt;/code&gt; with explicit checkout controls, or require environment approval before any AWS access in PR workflows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Methodology
&lt;/h2&gt;

&lt;p&gt;We used the GitHub Search API to find repositories containing &lt;code&gt;configure-aws-credentials&lt;/code&gt; in their &lt;code&gt;.github/workflows/&lt;/code&gt; directory. For each repository, we fetched all workflow YAML files and analyzed them for credential patterns, OIDC configuration, role ARN exposure, trigger types, and environment usage. The scan covered 10,000 unique repositories across all languages and star counts. All data is from publicly accessible GitHub repositories.&lt;/p&gt;

&lt;h2&gt;
  
  
  The full dataset
&lt;/h2&gt;

&lt;p&gt;We're publishing the complete statistical breakdown as part of our upcoming "State of OIDC Security 2026" report. If you want early access or have questions about the methodology, reach out at &lt;a href="mailto:security@trustfix.dev"&gt;security@trustfix.dev&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can scan your own AWS account for OIDC trust policy misconfigurations at &lt;a href="https://trustfix.dev" rel="noopener noreferrer"&gt;trustfix.dev&lt;/a&gt; — free for the first AWS account, no credit card required.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This research was conducted by TrustFix as part of the State of OIDC Security 2026 initiative. All data is from publicly accessible GitHub repositories analyzed via the GitHub API.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://trustfix.dev/blog/static-credentials-2026" rel="noopener noreferrer"&gt;trustfix.dev&lt;/a&gt;. TrustFix is a non-human identity security platform that detects trust policy misconfigurations and auto-generates validated Terraform fixes. Free CLI: &lt;code&gt;npx oidc-audit scan&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>security</category>
      <category>github</category>
      <category>sre</category>
    </item>
  </channel>
</rss>
