<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Token Timer - Your software assets management tool!]]></title><description><![CDATA[Token Timer - Your software assets management tool!]]></description><link>https://tokentimer.hashnode.dev</link><image><url>https://cdn.hashnode.com/uploads/logos/69e679c5c9501dd010229be2/e2bfb1ca-ced7-44a3-b113-1adbbdf8b4cb.jpg</url><title>Token Timer - Your software assets management tool!</title><link>https://tokentimer.hashnode.dev</link></image><generator>RSS for Node</generator><lastBuildDate>Tue, 13 Oct 2026 20:47:57 GMT</lastBuildDate><atom:link href="https://tokentimer.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[GitLab Deploy Token Metadata Belongs in a Reviewable Inventory]]></title><description><![CDATA[A GitLab deploy token created without an expiry date stays valid until it is revoked. That can be intentional. It becomes a problem when the team cannot say which project still uses it, who owns it, o]]></description><link>https://tokentimer.hashnode.dev/gitlab-deploy-token-metadata-belongs-in-a-reviewable-inventory</link><guid isPermaLink="true">https://tokentimer.hashnode.dev/gitlab-deploy-token-metadata-belongs-in-a-reviewable-inventory</guid><category><![CDATA[GitLab]]></category><category><![CDATA[api]]></category><category><![CDATA[deploy tokens]]></category><dc:creator><![CDATA[TokenTimer]]></dc:creator><pubDate>Mon, 28 Sep 2026 11:46:01 GMT</pubDate><content:encoded><![CDATA[<p>A GitLab deploy token created without an expiry date stays valid until it is revoked. That can be intentional. It becomes a problem when the team cannot say which project still uses it, who owns it, or when it was last reviewed.</p>
<p>GitLab does expose useful metadata. Self-Managed and Dedicated administrators can call <code>GET /deploy_tokens</code> for an instance-wide list. Project and group endpoints cover narrower permissions. The API returns fields including <code>expires_at</code>, scopes, and status. <a href="https://docs.gitlab.com/api/deploy_tokens/">GitLab's API documentation</a> is the right starting point for a homegrown audit.</p>
<h2>Turn the list into a reviewable inventory</h2>
<p>Keep the token name, project, expiry, and scopes together. Add an owner and a review date to each undated record. A scan only covers resources the GitLab account is permitted to read, so record that scope alongside the results.</p>
<h2>What to do with Never expires</h2>
<p>An undated deploy token should have a named owner and a review date even if the token must remain active. Check whether the consumer still exists and whether its scopes remain appropriate. GitLab documents setting expiry at creation, so replacing an existing undated token is the practical route when it needs an enforced expiry date.</p>
<p>Rotate in a safe order: create a replacement, update consumers, test the pipeline or registry operation with the new credential, and only then revoke the old token. For a group token named <code>gitlab-deploy-token</code>, GitLab populates <code>CI_DEPLOY_USER</code> and <code>CI_DEPLOY_PASSWORD</code> only in immediate child projects. Nested subgroups need separate attention.</p>
<h2>A repeatable audit</h2>
<ol>
<li><p>List accessible GitLab deploy tokens and preserve their metadata.</p>
</li>
<li><p>Review records marked Never expires and assign owners.</p>
</li>
<li><p>Record review dates where GitLab provides no expiry.</p>
</li>
<li><p>Replace unused or overprivileged tokens after testing consumers.</p>
</li>
<li><p>Repeat the inventory scan and compare it with the previous list.</p>
</li>
</ol>
<p>TokenTimer can preview a GitLab scan and import accessible metadata in one action without retrieving token values. Cloud scans are manual. Self-hosted installations can schedule GitLab re-scans. Access permissions still define the inventory's scope.</p>
<p>The goal is not an arbitrary expiry on every token. It is knowing which credentials still exist, who is responsible for them, and when someone will review them again.</p>
<p>Originally published on <a href="https://tokentimer.ch/blog/gitlab-deploy-token-expiry-inventory?utm_source=hashnode&amp;utm_medium=syndication&amp;utm_campaign=gitlab-deploy-token-expiry-inventory&amp;utm_content=gitlab-deploy-token-expiry-inventory-hashnode">TokenTimer</a>.</p>
]]></content:encoded></item><item><title><![CDATA[768 Leaked AWS Keys Had Full Admin Access. Most Were Years Old]]></title><description><![CDATA[An AWS key can disappear from a public repository and still work in AWS.
The credential still has an identity, a permission set, unknown copies, and possibly live dependencies. Removing that authentic]]></description><link>https://tokentimer.hashnode.dev/768-leaked-aws-keys-had-full-admin-access-most-were-years-old</link><guid isPermaLink="true">https://tokentimer.hashnode.dev/768-leaked-aws-keys-had-full-admin-access-most-were-years-old</guid><dc:creator><![CDATA[TokenTimer]]></dc:creator><pubDate>Sun, 06 Sep 2026 22:56:05 GMT</pubDate><content:encoded><![CDATA[<p>An AWS key can disappear from a public repository and still work in AWS.</p>
<p>The credential still has an identity, a permission set, unknown copies, and possibly live dependencies. Removing that authentication path requires revocation, while legitimate consumers need a working identity and the exposure needs an activity review.</p>
<p>Research from <a href="https://trufflesecurity.com/blog/leaked-corporate-aws-keys-held-full-admin-rights">Truffle Security</a> illustrates this gap. The company tested 10,616 complete AWS key pairs again after they had appeared publicly between August 2022 and August 2026. On August 10, 2026, 9,308 of them, or 88%, still authenticated.</p>
<p>The findings raise two distinct questions: how much access did the keys retain, and what would make those authentication paths stop working?</p>
<h2>The research measured persistence, not just exposure</h2>
<p>Truffle Security's scanners had historically verified 64,024 unique AWS key pairs across 431,875 public findings. Those findings included Git history, Hugging Face datasets, Docker images, package registries, and CI logs.</p>
<p>Researchers retained complete credentials for 10,616 of the unique pairs and tested that population again. The result was not a list of strings that merely looked like AWS keys. It was a set of credentials checked for successful authentication, with 9,308 still active.</p>
<p>That difference is important. Removing a key from its original repository does not disable it in AWS. Exposure exists wherever a copy can be found; validity is controlled by the identity provider. A response process has to connect the two.</p>
<h2>Persistent AWS access keys have no automatic ending</h2>
<p>Traditional IAM access keys are persistent credentials. Unlike temporary credentials issued through IAM roles or AWS STS, they do not reach the end of a short session and stop working. AWS documents that <a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/securing_access-keys.html">IAM user access keys remain valid until they are manually revoked</a> and recommends temporary credentials wherever possible.</p>
<p>This creates a particular kind of infrastructure drift. An application can be retired, a developer can leave, a migration can finish, and a sandbox account can be forgotten. None of those events changes the state of the key.</p>
<p>The surrounding reason disappears. The authentication path remains.</p>
<p>For 2,903 active credentials that permitted <code>iam:ListAccessKeys</code>, the researchers could retrieve exact creation dates. The median key was 1,831 days old, a little over five years. Only 25 had been created in the previous 30 days. Just 13.7% had a newer access key associated with the same user, suggesting that rotation was uncommon within this population.</p>
<p>That median measures age since creation, not time since exposure. It applies to these 2,903 keys, not specifically to the corporate admin keys examined below.</p>
<p>A forgotten certificate eventually reaches its expiration time. A forgotten persistent AWS key does not have that automatic boundary.</p>
<h2>Hundreds retained authority across an entire account</h2>
<p>Age becomes more serious when combined with privilege.</p>
<p>Truffle Security classified 817 active keys as linked to businesses. Of those:</p>
<ol>
<li><p>526 were root access keys.</p>
</li>
<li><p>Another 242 belonged to IAM users with <code>AdministratorAccess</code>.</p>
</li>
<li><p>The two groups did not overlap.</p>
</li>
</ol>
<p>Together, 768 credentials provided full control of a company AWS account. The research also identified 130 active root keys belonging to AWS Organizations management accounts.</p>
<p>AWS <a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/root-user-best-practices.html">strongly recommends not creating access keys for the root user</a>. The root user has full access to the account, so existing root access keys should be removed.</p>
<p>Least privilege is not an abstract improvement in this scenario. It determines whether one copied secret grants a narrow workload capability or control over an account.</p>
<h2>A quarantine signal is not the same as revocation</h2>
<p>One of the most revealing findings involved credentials AWS had already detected as exposed.</p>
<p>The researchers found 929 active IAM users with the <code>AWSCompromisedKeyQuarantine</code> policy attached. AWS had restricted those users, yet their credentials still authenticated. Among them, 112 carried the original policy version that AWS stopped applying in 2023, indicating that they had been flagged at least three years earlier.</p>
<p>Quarantine can reduce immediate capability, but a human or automated workflow still has to resolve ownership and dependencies. If a team cannot tell which production job uses a key, disabling it can create an outage. If nobody accepts that risk and no migration is scheduled, the compromised identity can remain indefinitely.</p>
<p>The completion condition for an alert from secret scanning should therefore be stronger than “finding acknowledged” or “policy attached.” It should include evidence that the exposed credential has been revoked and that any legitimate consumer now uses an approved replacement.</p>
<h2>Public copies spread beyond source repositories</h2>
<p>The propagation path has also widened.</p>
<p>Truffle Security reported 8,482 unique live AWS keys across 3,394 public Hugging Face datasets. Training datasets can include snapshots of source code collected elsewhere. A key committed once can be copied into datasets, images, archives, forks, caches, and downstream projects.</p>
<p>Deleting the original file cannot recall those copies. It also cannot make a credential secret again. Once a credential has been public, assume it has been copied and revoke it.</p>
<p>This gives secret scanning and credential lifecycle management distinct responsibilities:</p>
<ol>
<li><p><strong>Scanning</strong> asks where a secret has appeared.</p>
</li>
<li><p><strong>Lifecycle control</strong> asks whether it is still valid, who owns it, what depends on it, what it can access, and when it will be removed.</p>
</li>
</ol>
<p>An organization needs both. Neither is a substitute for the other.</p>
<h2>Why a policy based on 90 days is incomplete</h2>
<p>The AWS Config <code>access-keys-rotated</code> control <a href="https://docs.aws.amazon.com/config/latest/developerguide/access-keys-rotated.html">uses 90 days as its default maximum age</a>. That can be a useful backstop, but key age answers only one governance question.</p>
<p>It does not tell you:</p>
<ol>
<li><p>Whether the identity still has a valid purpose.</p>
</li>
<li><p>Who is accountable for it.</p>
</li>
<li><p>Which applications will fail if it is disabled.</p>
</li>
<li><p>Whether its permissions are still appropriate.</p>
</li>
<li><p>Where copies may exist.</p>
</li>
<li><p>Whether the replacement reached every consumer.</p>
</li>
<li><p>Whether the old credential was actually deleted.</p>
</li>
</ol>
<p>Routine rotation can leave two active keys if the replacement is created but the original is never removed. Disabling the old key without accounting for its consumers can instead create an outage.</p>
<p>Treat routine rotation as a dependency migration, not a timestamp update. An exposed key requires a more urgent response.</p>
<h2>An incident runbook for an exposed key</h2>
<p>When a persistent access key becomes public, treat it as compromised. The responsibilities below need observable outcomes, but they are not a rigid migration order: revocation must not automatically wait for every consumer to move.</p>
<h3>1. Identify the credential and its authority</h3>
<p>Resolve the AWS account, IAM user or root identity, attached permissions, expected use, recent activity, owner, and known consumers. Root credentials and credentials with administrator access have the broadest blast radius.</p>
<h3>2. Contain and revoke</h3>
<p>Prioritize restricting access and disabling or deleting the exposed key. Coordinate the availability impact with the workload owner. A quarantine policy or a deleted public copy is not evidence that the AWS key has been revoked.</p>
<h3>3. Decide whether a replacement is necessary</h3>
<p>If the workload can use an IAM role, workload identity, federation, or AWS STS, migrate toward temporary credentials. If a persistent key remains unavoidable, create a replacement with the permissions the workload actually needs.</p>
<h3>4. Migrate every dependency</h3>
<p>Update each known consumer and verify it operates with the intended identity. Ownership and dependency records help reduce the risk of a security response becoming an availability incident.</p>
<h3>5. Review activity and verify the result</h3>
<p>Review the exposed key's activity and permissions, confirm the intended identity is in use, and verify that the old key no longer authenticates. Revocation removes this authentication path; it does not by itself establish that the wider incident is resolved.</p>
<h2>Build a lifecycle that removes obsolete paths</h2>
<p>The durable controls are straightforward to state, even when migration work is not:</p>
<ol>
<li><p>Prefer temporary credentials for people and workloads.</p>
</li>
<li><p>Remove root access keys from all accounts, including development, sandbox, and Organizations management accounts.</p>
</li>
<li><p>Inventory every persistent key that remains.</p>
</li>
<li><p>Assign a responsible person or team and an explicit review or rotation deadline.</p>
</li>
<li><p>Apply least privilege so one workload does not administer an entire account.</p>
</li>
<li><p>Scan repositories, CI/CD systems, images, registries, and datasets independently of the lifecycle inventory.</p>
</li>
<li><p>Treat rotation as complete only after dependencies use the replacement and the old key is disabled or deleted.</p>
</li>
</ol>
<p>AWS's broader <a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html">IAM security best practices</a> also emphasize temporary credentials, least privilege, and regular removal of unused identities, policies, and credentials.</p>
<h2>Where inventory tooling fits</h2>
<p>TokenTimer tracks inventory, ownership, and lifecycle status through metadata, not public secret scanning. Its AWS integration can discover IAM access key metadata alongside Secrets Manager secrets and ACM certificates without retrieving or storing secret access key values.</p>
<p>Because AWS supplies no expiration date for IAM keys, they import as nonexpiring assets by default. Teams can assign an internal review or rotation date. That is an operational deadline, not automatic expiry of the AWS key.</p>
<h2>The operational lesson</h2>
<p>The 768 credentials with full control show the potential blast radius. Separately, the age measurements show how long persistent credentials can remain valid.</p>
<p>Applications change. Teams reorganize. Experiments end. Copies spread. A persistent credential can remain stable through all of it because AWS does not infer that its purpose has disappeared.</p>
<p>When a persistent key is unavoidable, give it a named owner, constrained authority, a review deadline, a tested replacement path, and a removal condition. Detection produces a finding. Revocation removes the exposed authentication path, while activity and permission review remain part of the response.</p>
<p>Originally published on <a href="https://tokentimer.ch/blog/aws-access-keys-leaked-admin-rights?utm_source=hashnode&amp;utm_medium=syndication&amp;utm_campaign=aws-leaked-admin-keys-2026&amp;utm_content=aws-leaked-admin-keys-hashnode">TokenTimer</a>.</p>
]]></content:encoded></item><item><title><![CDATA[AWS Access Keys Don’t Expire: Govern the Exceptions, Not Just the Rotation Date]]></title><description><![CDATA[An AWS IAM user access key can remain valid long after the workload, integration, or person that needed it is gone.
The credential does not know that a migration finished or a pipeline was replaced. U]]></description><link>https://tokentimer.hashnode.dev/aws-access-keys-don-t-expire-govern-the-exceptions-not-just-the-rotation-date</link><guid isPermaLink="true">https://tokentimer.hashnode.dev/aws-access-keys-don-t-expire-govern-the-exceptions-not-just-the-rotation-date</guid><dc:creator><![CDATA[TokenTimer]]></dc:creator><pubDate>Fri, 28 Aug 2026 09:40:41 GMT</pubDate><content:encoded><![CDATA[<p>An AWS IAM user access key can remain valid long after the workload, integration, or person that needed it is gone.</p>
<p>The credential does not know that a migration finished or a pipeline was replaced. Unless someone explicitly deactivates or deletes it, the authentication path remains available. That makes long-lived access keys a lifecycle problem before they become a rotation problem.</p>
<p>A calendar can tell you when a key should change. It cannot tell you whether the key should still exist.</p>
<h2>Long-term and temporary credentials have different failure modes</h2>
<p><a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/securing_access-keys.html">AWS guidance on securing access keys</a> distinguishes long-term IAM user credentials from temporary credentials. An IAM user access key has no automatic expiration. Credentials issued through IAM roles and AWS Security Token Service have defined lifetimes and stop working when their sessions expire.</p>
<p>Workload identity, roles, and OIDC federation let applications and CI/CD systems obtain temporary access without storing a permanent AWS secret. That architectural choice changes the operating burden.</p>
<p>A persistent key has to be protected everywhere it is copied, inventoried for as long as it exists, monitored for unexpected use, rotated without breaking consumers, and eventually removed. Temporary credentials do not solve authorization by themselves, but they remove indefinite lifetime from the default design. AWS makes the same preference explicit in its <a href="https://docs.aws.amazon.com/wellarchitected/latest/framework/sec_identities_unique.html">guidance on temporary credentials</a>.</p>
<p>The practical order is therefore:</p>
<ol>
<li><p>Eliminate the persistent key where possible.</p>
</li>
<li><p>Use temporary identity for people and workloads.</p>
</li>
<li><p>Treat every remaining long-lived key as an owned exception with an end condition.</p>
</li>
</ol>
<h2>Evidence from real exposure campaigns</h2>
<p>The danger is not theoretical, and the exposure window is not measured in quarterly review cycles.</p>
<p>A 2024 experiment <a href="https://www.helpnetsecurity.com/2024/12/02/revoke-exposed-aws-keys/">summarized by Help Net Security</a> planted AWS credentials across public platforms. Keys on GitHub and Docker Hub were found and used within minutes, while other platforms took hours or days. The exact timing varies, but the defensive conclusion does not: a manual response process cannot assume that a public credential will remain unused while a human investigates.</p>
<p>Palo Alto Networks Unit 42 documented an automated cryptojacking campaign called <a href="https://unit42.paloaltonetworks.com/malicious-operations-of-exposed-iam-keys-cryptojacking/">EleKtra-Leak</a>. The actor continuously scanned public GitHub repositories for AWS IAM credentials. In controlled leaks, Unit 42 saw a plaintext key detected and used within five minutes, followed by attempts to create EC2 capacity for cryptocurrency mining.</p>
<p>Between August 30 and October 6, 2023, the researchers observed 474 distinct miners that appeared to run on actor-controlled EC2 instances. They found that the campaign had been active since at least 2020. This was repeatable infrastructure designed to turn an exposed authentication path into compute, not a one-off attacker stumbling across a secret.</p>
<h2>The <code>.env</code> campaign shows how exposure becomes cloud compromise</h2>
<p>A separate <a href="https://unit42.paloaltonetworks.com/large-scale-cloud-extortion-operation/">Unit 42 cloud-extortion investigation</a> followed a campaign that searched public web applications for exposed <code>.env</code> files.</p>
<p>The actor scanned more than 230 million unique targets, reached at least 110,000 domains, and collected more than 90,000 unique environment variables. Thousands of those variables were associated with cloud services.</p>
<p>Valid cloud credentials allowed the actor to enumerate identity and storage resources, exfiltrate data, leave ransom notes, and use compromised infrastructure to search for more victims. This campaign connects two parts of the lifecycle that teams sometimes review separately: where a credential is stored and whether the authentication path behind that copy is still valid.</p>
<p>A young key in a public <code>.env</code> file can be immediately dangerous. An old, dormant key remains a standing risk until it is revoked. Rotation age alone does not describe either situation.</p>
<h2>An exception needs enough context to be governed</h2>
<p>Some legacy applications and integrations still require IAM user access keys. Calling those keys “exceptions” is useful only if the exception has a concrete record.</p>
<p>For each persistent key, document:</p>
<ul>
<li><p>the named owner;</p>
</li>
<li><p>the workload and purpose;</p>
</li>
<li><p>why temporary credentials are not yet suitable;</p>
</li>
<li><p>the permissions the workload requires;</p>
</li>
<li><p>creation and last-use information;</p>
</li>
<li><p>expected behavior;</p>
</li>
<li><p>known storage locations;</p>
</li>
<li><p>the approved lifetime and review date;</p>
</li>
<li><p>the replacement strategy;</p>
</li>
<li><p>the condition that will retire the exception.</p>
</li>
</ul>
<p>The final item prevents a temporary workaround from quietly becoming permanent infrastructure. If the team cannot explain what will make a key disappear, a rotation schedule may keep refreshing the credential without reducing the number of persistent authentication paths.</p>
<h2>Storage review and lifecycle review belong together</h2>
<p>Removing a secret from current application configuration does not remove all of its copies. Long-lived keys can survive in source repositories, Git history, container layers, CI/CD variables, backups, environment files, and old deployment configuration.</p>
<p>Secret discovery identifies places where credentials may have escaped. Lifecycle review answers a different set of questions: Is the key still valid? Who owns it? What can it access? Is its use expected? Can it be disabled now?</p>
<p>Both matter because deleting a line from a file does not revoke the credential. The response path needs to lead from detection to deactivation, investigation, replacement where required, and removal of the old authentication path.</p>
<h2>Rotation should prove that the old path is gone</h2>
<p>For a persistent key that cannot yet be eliminated, treat rotation as a migration:</p>
<p><strong>Create → Deploy → Verify → Deactivate → Monitor → Delete</strong></p>
<p>Creating a replacement key is only the first state. Every consumer must receive it, the workload must be verified, and use of the old key must stop before that old path can be safely disabled and deleted.</p>
<p>If the old key remains active, rotation may simply leave two working credentials. If it is disabled too early, a dependency that never received the replacement can fail. The meaningful outcome is evidence that the old authentication path is no longer required.</p>
<h2>Practical takeaways</h2>
<ul>
<li><p>Prefer temporary credentials over permanent secrets.</p>
</li>
<li><p>Make every unavoidable long-lived key visible as an exception.</p>
</li>
<li><p>Track ownership, purpose, age, last use, permissions, storage, and replacement.</p>
</li>
<li><p>Prepare a fast deactivation path before exposure occurs.</p>
</li>
<li><p>Treat rotation as complete only when the old key is removed.</p>
</li>
</ul>
<h3>Do AWS IAM access keys expire automatically?</h3>
<p>No. Long-term access keys for IAM users remain valid until they are manually deactivated or deleted. Temporary credentials issued through roles and STS expire after a defined period.</p>
<h3>Should a team rotate long-lived keys or eliminate them?</h3>
<p>Eliminate them where roles, workload identity, or OIDC federation can provide temporary credentials. Govern unavoidable exceptions with least privilege, a named owner, age and last-use review, and a tested replacement process.</p>
<h3>What should the next access-key review ask?</h3>
<p>Keep asking when the key was last rotated, but add the question that exposes lifecycle debt:</p>
<p><strong>Why does this persistent credential still exist, and what will make it disappear?</strong></p>
<p>Originally published on <a href="https://tokentimer.ch/blog/aws-access-keys-no-rotation-policy-risk?utm_source=hashnode&amp;utm_medium=syndication&amp;utm_campaign=aws-access-key-risk-2026&amp;utm_content=aws-key-risk-hashnode">TokenTimer</a>.</p>
]]></content:encoded></item></channel></rss>