> ## Content Index
> Fetch the complete content index at: https://articles.akadata.co.uk/llms.txt
> Use this file to discover other available public pages before exploring further.

# Tech Scroll 133: OWASP When the Public Record Did Not Match the Explanation
- URL: https://articles.akadata.co.uk/owasp-the-day-facts-did-not-match-reality/
- Published: 2026-09-22T17:13:56.000Z
- Updated: 2026-09-22T17:31:22.000Z
- Author: AKADATA
- Tags: Tech Scroll

> **Our opinion counts for squat. The public record is what matters.**

*A review of the public evidence surrounding the temporary takeover of `api-security.owasp.org` on 21 September 2026.*

> A gate stood open in the city wall.  
> The keeper said, “The road has failed.”  
> Yet the road was sound. The latch had been left unfastened, and strangers had entered.  
> The travellers knew only this: the gate that should have protected them did not.  
> *“The first to present their case seems right, till another comes forward and questions them.”*  
> — Proverbs 18🕔

## OWASP When the Public Record Did Not Match the Explanation  

This article works only from public artefacts: web-archive captures, public repository history, DNS answers, registration records, official documentation, and published statements. It has no access to private logs held by OWASP, GitHub, Cloudflare, a DNS provider, or the party whose notice appeared on the site.

[https://api-security.owasp.org/](https://api-security.owasp.org/?ref=articles.akadata.co.uk)

<https://web.archive.org/web/20260921044305/https://api-security.owasp.org/>

![](https://articles.akadata.co.uk/content/images/2026/09/image.png)

<https://web.archive.org/web/20260921152033/https://api-security.owasp.org/>

<https://web.archive.org/web/20260921212543/https://api-security.owasp.org/>

![](https://articles.akadata.co.uk/content/images/2026/09/image-1.png)

It draws no conclusion about civil or criminal liability, does not identify an individual operator, and is not legal advice. Where the public record cannot settle a point, that uncertainty is stated plainly.

## The conclusion in brief  

On 21 September 2026, `api-security.owasp.org` stopped serving the expected API Security project material and began serving a third-party notice page. The public evidence strongly supports a GitHub Pages custom-domain binding being removed during a forced documentation deployment, which left the hostname claimable on the platform until the binding was restored.

That is not evidence that the `owasp.org` registration expired, that the authoritative DNS zone was hijacked, or that an OWASP server, registrar account, DNS account, or GitHub account was penetrated. It is, nevertheless, a real compromise of an official web property: visitors to an OWASP hostname were served pages selected by someone outside OWASP.

The technical distinction matters. A production subdomain becoming claimable through a deployment fault is not a trivial event merely because it is not a deep systems breach.

## What is established  

The available timestamps create a clear outer window:

| Time (UTC)             | Public evidence                       | What it establishes                                                              |
| ---------------------- | ------------------------------------- | -------------------------------------------------------------------------------- |
| 11 September, 18:48:24 | Commit ed89451 adds CNAME to gh-pages | The GitHub Pages custom-domain binding existed.                                  |
| 21 September, 04:43:05 | Web archive capture                   | The expected OWASP API Security site was still visible.                          |
| 21 September, 12:41:59 | Commit 9ef4ea0                        | A forced MkDocs deployment replaced the published branch without the CNAME file. |
| 21 September, 15:20:33 | Web archive capture                   | A NOX-branded security notice was visible at the official hostname.              |
| 21 September, 21:25:43 | Web archive capture                   | The third-party page remained visible.                                           |
| 22 September, 14:25:04 | Commit 3d6e4df                        | The CNAME file was restored.                                                     |

The archive proves the change occurred after 04:43:05 and before 15:20:33\. The deployment at 12:41:59 is the most plausible public trigger inside that window. The public record does not reveal the exact time a third party made its claim, nor the exact time the restored page reached every cache and edge location.

## The mechanism: DNS was involved, yet it was not a DNS expiry

A GitHub Pages custom domain has two separate parts:

1. **DNS routing** directs a hostname to GitHub Pages.
2. **Platform binding** tells GitHub Pages which published site is entitled to answer for that hostname. In this project, that binding was represented by a `CNAME` file in the published branch.

Both must remain in place. Where the DNS record continues to send traffic to GitHub Pages and the platform binding disappears, the hostname can become available to another GitHub Pages account. GitHub’s own documentation warns that static-site generators using force-push deployments can overwrite a `CNAME` file and expose a custom domain to takeover.

The public workflow invoked `mkdocs gh-deploy --force`. The relevant deployment commit replaced the `gh-pages` branch with new history and no `CNAME` file. The later repair re-added that file.

That sequence explains the event without requiring an expired domain, a nameserver takeover, or stolen credentials.

## What “a domain expired” gets wrong

`api-security.owasp.org` is a hostname beneath the registered parent domain `owasp.org`; it is not a separately registered domain object. The supplied registration record states that `owasp.org` remains registered until September 2031.

No public evidence presented here shows that the parent registration expired. No public evidence shows that OWASP’s authoritative zone changed hands. The failed object was the GitHub Pages custom-domain association, not the `owasp.org` registration.

Calling the incident “DNS” can be useful as shorthand only where the layer is made clear. DNS remained part of the route. The observed failure was a lost hosting-platform binding that left an official child hostname claimable.

## Was OWASP hacked?

The answer depends on the scope of the word.

At the visitor-facing level, an official OWASP hostname served unauthorised third-party pages. That is a compromise of the web property’s integrity and a legitimate security incident.

At the deeper infrastructure level, the public evidence does **not** establish compromise of OWASP servers, source code, user records, registrar credentials, authoritative DNS, CDN credentials, or GitHub account credentials. Normal deployment history plus the missing binding adequately explains what is visible.

The careful conclusion is therefore narrower than either extreme: the public web property was compromised; wider penetration is not established.

## The public explanation and the public record

A Reddit comment apparently made by OWASP’s Executive Director described the event as an expired domain and rejected the term “hacked.” The account is strongly associated with the Executive Director’s established public identity, although a forum post is not cryptographic proof of authorship.

The public record does not support the expired-registration explanation. It also does not support claims of a wider systems breach. These are not contradictory findings:

- the parent domain did not expire on the supplied registration record;
- the GitHub Pages binding was removed in a forced deployment;
- the official hostname then displayed third-party pages;
- no public artefact demonstrates deeper compromise.

An incident statement could have acknowledged the unauthorised control of the hostname while making the same important qualification about the absence of evidence for server or account penetration. That would have been more accurate and harder to misunderstand.

## Why the incident matters

The observed impact was limited to unauthorised content and branding on a trusted hostname. There is no public evidence here of data loss or user compromise.

The potential impact of a claimed subdomain can, however, be more serious. OWASP’s own subdomain-takeover guidance discusses phishing, trust in a familiar origin, cookie scope, redirect allowlists, and cross-origin assumptions as possible risks. Those are risk categories, not findings in this event; none should be reported as having happened without evidence.

The key operational failure is straightforward: a deployment was able to remove a production hostname binding without an automated guardrail, and the condition remained publicly visible long enough for a third party to serve content at that hostname.

## The recurrence question

Restoring `CNAME` to the published branch returned the site to its expected state. A durable repair needs more than a manual restoration.

The source documentation and deployment process need to preserve the custom-domain declaration on every deployment. A sensible control set would include:

- storing the expected hostname in the deployment source or generator configuration;
- failing the pipeline where the generated publication output does not contain the expected binding;
- verifying and protecting the custom domain at the hosting platform;
- continuously checking for dangling DNS-to-hosting records and unexpected content;
- maintaining an inventory linking each hostname to its DNS record, hosting service, repository, owner, and decommissioning state.

The public workflow used a force deployment and the source branch did not visibly preserve the binding. That means the underlying deployment defect appeared unresolved at the time of review. Hidden hosting-platform safeguards may reduce the ability to claim the hostname; they would not by themselves prevent a future outage caused by a missing binding.

## Detailed reconstruction of the event

  
The short version is easy to state: the custom-domain binding disappeared, the hostname became claimable, and a third-party notice appeared. The longer version matters because the competing public descriptions use the word “domain” for several different things.

At the registration layer, `owasp.org` is the registrable name. The supplied registration record states that it was created in 2001 and was due to remain registered until September 2031\. At the DNS layer, a record for `api-security.owasp.org` determines where browsers should send requests for the child hostname. At the hosting layer, GitHub Pages needs to know which published site may answer for that hostname. At the content layer, the account holding that hosting association controls the pages a visitor receives.

Those layers can fail independently. A registrar lapse can cause a parent name to be lost. A zone-account compromise can alter DNS answers. A hosting-account compromise can replace a site. A dangling custom-domain association can allow a new account to attach its own pages to an existing routed hostname. The public evidence points to the fourth case.

The distinction is more than terminology. Each class of incident has a different scope, different evidence, different recovery actions, and a different public statement. Saying that a registrar expiry occurred would imply a failure in the control of the parent registration. Saying that the authoritative zone was hijacked would imply unauthorised control of the DNS configuration. Saying that an account or server was breached would imply some form of credential or infrastructure compromise. The available public sequence requires none of those explanations.

The publication branch provides the clearest visible trail. On 11 September, the project added a file named `CNAME` to `gh-pages`. Its content bound the project’s GitHub Pages output to `api-security.owasp.org`. The page captured on 21 September at 04:43 UTC was the expected API Security Top 10 site. That establishes that the binding was live at that time.

At 12:41:59 UTC, a deployment commit replaced the branch through the project’s documentation deployment process. The public workflow invokes `mkdocs gh-deploy --force`. The resulting published commit did not contain `CNAME`. This does not prove the first second that a third party could claim the name: GitHub’s internal state, propagation and verification controls are not public. It does establish that the visible repository declaration had gone.

By 15:20:33 UTC, the Internet Archive had captured a page headed “Security Notice | NOX Offensive Security” at the official OWASP hostname. It remained visible in a later capture at 21:25:43 UTC. On 22 September, the project restored `CNAME` in a new commit. The expected project pages then returned.

That is a coherent causal chain. The site was normal; the durable binding was removed by a force deployment; a third-party notice became visible under the same hostname; then the binding was restored. The chain remains an evidence-led reconstruction rather than access to OWASP’s private platform logs. A hidden configuration could have affected the precise moment of claimability. No hidden configuration is needed to explain the public outcome.

## What the archive captures do and do not prove  

Web archives are powerful evidence, however they are not continuous monitoring systems. A capture at 04:43:05 shows the representation returned to the archive at that point. A capture at 15:20:33 shows a different representation was available then. They establish an outer window of 10 hours, 37 minutes and 28 seconds. They do not prove the exact transition time, every intervening response, or what individual visitors received from every network location.

The two archive pages are still valuable because they are independently reproducible public artefacts. Each can be checked directly for its page title, visual content, and timestamp. The first shows the expected project title. The second records the third-party notice. The later capture demonstrates that the event was not a fleeting archive anomaly.

The public repository history narrows the likely trigger within that outer window. It does not establish the identity of the individual who claimed the hostname. It does not show private GitHub verification settings, audit events, or all DNS configuration. This article makes no claim beyond those limits.

Current DNS answers and HTTP headers also require restraint. A later lookup returning Cloudflare-fronted addresses and a response with Cloudflare headers proves the live hostname was then being served through Cloudflare. It does not establish why that fronting was introduced, who made the change, or whether it was part of the incident response. It must not be presented as proof of an emergency measure or a DNS compromise.

Similarly, the reappearance of the `CNAME` file proves that the repository’s visible association was restored. It does not, by itself, prove the exact moment GitHub Pages accepted it, the exact cache-expiry moment at every edge, or the completion of any wider security review.

## The GitHub Pages custom-domain failure mode  

GitHub Pages supports publishing a static site beneath a name such as `api-security.owasp.org`. The platform must be told that the name belongs to a particular Pages site, while DNS must be configured to route the name to the platform. For many Pages workflows, the declaration is stored as a `CNAME` file in the branch or output directory that Pages serves.

Static-site generators can make this fragile. A typical generator renders a clean output tree and then publishes it. A force deployment deliberately rewrites the destination branch. It is useful for keeping generated content clean; it also removes files that are absent from the new output. Where the custom-domain declaration exists only in the published branch and not in the source or generated output, a new force deployment can delete it.

GitHub documents this exact operational risk in its custom-domain troubleshooting guidance. The relevant warning is not proof that every GitHub Pages configuration behaves identically, and it does not prove any party’s intention. It does show that the mechanism is known, foreseeable, and preventable.

The `CNAME` file should therefore be treated as production configuration, not as incidental build output. It needs a durable source of truth and a deployment check. A workflow that can deploy a documentation change while silently discarding the custom hostname is an infrastructure workflow with an incomplete invariant.

The missing invariant is simple: the output intended for the production hostname must declare that hostname before publication. A pipeline can check this in a few seconds. The build should fail where the expected `CNAME` is missing, malformed, or changed without review. The same principle applies to a platform-managed domain setting rather than a file: the expected binding should be tested after deploy and alerted on when it changes.

## Why “it was DNS” is only partly useful  

The phrase has become a familiar engineering joke because DNS often sits somewhere in the path of an outage. In this event, DNS undeniably sat in the route from visitor to host. The phrase becomes misleading where it is allowed to imply that DNS itself expired, that the authoritative zone was taken over, or that the remedy was simply to move registrations between providers.

The authoritative evidence needed for a zone hijack would include a published zone-history change, nameserver change, registrar account record, provider audit evidence, or materially altered DNS answers. No such artefact is set out here. The supplied WHOIS data points in the opposite direction on the expiry question: the registered parent remained active.

The more exact description is: a resolution-adjacent subdomain takeover caused by loss of a static-hosting custom-domain binding. It is less catchy, however it tells engineers where the failure occurred. The DNS route remained useful to the third party because it still delivered visitors to the hosting platform. The platform association no longer reserved the hostname for the intended project.

That matters operationally. An organisation responding to the wrong layer may renew a registration, consolidate a registrar, or rotate DNS credentials and still leave the deployment capable of recreating the same problem. Registration hygiene and DNS-account security remain important; neither replaces a durable platform binding and post-deployment validation.

## Impact: observed facts and unobserved risks  

The observed impact is clear and should not be minimised: visitors who followed an OWASP API Security hostname could receive unauthorised third-party content. The visual integrity of the web property was lost for a period measured in hours. A security organisation’s trusted namespace was used to display another organisation’s message.

The evidence does not establish theft of source code, personal data, credentials, payment data, or server-side records. It does not establish phishing, malware, malicious redirects, certificate issuance, cookie theft, cache poisoning, search-index poisoning, or exploitation of cross-origin trust. None of those should be asserted as an incident finding.

They remain relevant as possible exposure categories because an externally claimable child hostname can carry user trust inherited from its parent. OWASP’s own Subdomain Takeover Prevention Cheat Sheet explains why this class of weakness can create risks around convincing content, cookies, wildcard policies, redirect allowlists, and other trust relationships. A sound incident review would check those areas and publish only the results that evidence supports.

This difference between observed impact and potential impact is central to responsible reporting. Treating every possibility as a confirmed consequence would be reckless. Pretending that a confirmed hostname takeover had no significance because a deeper breach was not shown would be equally misleading.

## The NOX attribution boundary  

The archived page identified NOX Offensive Security and linked to its public website. That is direct evidence of what the page represented itself to be. It supports attribution of the displayed notice to the NOX brand at the time of capture.

It does not establish the legal identity of the domain registrant, the identity of the person operating a keyboard, the knowledge or approval of every associated individual, or civil or criminal responsibility. Public company-directory material may describe an organisation’s public identity; it cannot establish incident operation by an individual. For that reason, this article does not name people associated with the business, and does not attempt a legal analysis of Brazilian law.

The ethical question is also better kept separate from the technical reconstruction. Responsible disclosure normally involves reporting a weakness through an authorised channel and avoiding unnecessary changes to a live production property. The public comments state that OWASP could not locate an earlier report through its normal channels. That claim is inherently internal: only the organisation has complete visibility of what it received, and only the claimant can provide its own evidence of attempted contact. The public record cannot settle it.

No sponsor funded this review, and no commercial relationship with either organisation is claimed. The purpose is not to declare a winner in an online argument. It is to record what the public artefacts show and where they stop.

## Assessing the public response fairly  

The most defensible criticism of the public response is narrow. The description of an expired domain does not match the supplied registration record and does not match the visible GitHub Pages deployment history. The categorical dismissal of any compromise also obscures the visitor-facing reality that a trusted official hostname served unauthorised content.

The response was correct on one important point: the public evidence does not show a conventional server or account intrusion. The response was not technically precise enough on the underlying cause or the impact. Both propositions can be true at once.

A stronger statement would have said that an automated deployment removed the custom-domain binding for the affected hostname; that third-party pages were served under that hostname; that the team had restored the binding; and that there was no evidence, at that time, of registrar, DNS-provider, GitHub-account, or server credential compromise. It could then have addressed reporting conduct separately.

Such a statement would have protected readers from false escalation while avoiding false reassurance. It would also have made the organisation’s remediation measurable: a reader could ask whether the source build now carries the binding, whether the pipeline verifies it, and whether post-incident checks found any wider trust exposure.

## What recovery should look like  

Returning the normal page is containment. It is not enough, by itself, to establish root-cause correction. A credible recovery plan has four connected parts.

First, **make the association durable**. The expected custom hostname should be present in source control or generated output on every deployment. The deployment should stop rather than publish a branch missing the declaration.

Second, **lock and verify the name at the hosting platform**. GitHub Pages offers custom-domain verification controls intended to reduce the possibility of another account attaching a name. The owning platform account should be reviewed, evidence retained, and any available protection enabled.

Third, **monitor the production property**. A request to each production hostname should check expected status, expected content, TLS state, redirect behaviour, and unexpected changes. Monitoring should be independent of the deployment itself. A domain inventory should link each hostname to a DNS record, a hosting service, a repository, a named owner, and a retirement process.

Fourth, **review trust relationships**. The organisation should consider cookies scoped to parent or subdomains, redirect allowlists, CORS and origin assumptions, authentication callbacks, certificate-transparency events, CDN logs, and any traffic or cache effects during the visible window. The review need not publish sensitive operational detail; it should publish a clear conclusion about the categories examined and any material outcome.

The public record suggested that the workflow still used a force deployment while the source branch contained no visible durable input for the custom-domain association. That leaves a recurrence concern. A manual repair made only in the generated publication branch can be deleted by the next clean deployment. The correct test is not whether the page looks normal today; it is whether a fresh deployment can be proved to preserve the hostname binding.

## Findings and confidence  

The following grades describe the evidence, not the value of any organisation.

| Proposition                                                      | Assessment                 | Confidence       | Basis and limit                                                                                         |
| ---------------------------------------------------------------- | -------------------------- | ---------------- | ------------------------------------------------------------------------------------------------------- |
| The expected site was visible at 04:43 UTC                       | Established                | High             | Archive capture; no continuous monitoring.                                                              |
| A forced deployment omitted CNAME at 12:41 UTC                   | Established                | High             | Public commit and workflow; private platform settings unavailable.                                      |
| A third-party notice was visible by 15:20 UTC                    | Established                | High             | Archive capture; exact first-live time unknown.                                                         |
| The notice persisted into the evening                            | Established                | High             | Later archive capture; intermittent behaviour cannot be excluded.                                       |
| The binding was restored on 22 September                         | Established                | High             | Public repair commit; edge-propagation time unknown.                                                    |
| owasp.org expired                                                | Refuted by supplied record | High             | Parent registration dates; not a claim about every historical configuration.                            |
| The authoritative DNS zone was hijacked                          | Not established            | High             | No public zone-change evidence presented.                                                               |
| The official web property was compromised                        | Established                | High             | Unauthorised third-party pages appeared on its hostname.                                                |
| An OWASP account, server, registrar, or DNS account was breached | Not established            | Moderate to high | Public sequence explains event without it; private logs unavailable.                                    |
| The claimant brand was associated with the notice                | Supported at brand level   | Moderate         | Self-identification on archived page; individual operator unproven.                                     |
| The condition could recur without a deployment fix               | Supported                  | Moderate         | Force workflow and absence of visible source binding; hidden platform controls may affect claimability. |

## The conclusion  

The public evidence supports a real, avoidable takeover of an official OWASP child hostname through loss of a GitHub Pages custom-domain binding. It does not support a registrar-expiry story, an authoritative-DNS hijack story, or a wider server-and-credentials breach story.

That distinction is not a defence for the failure. It is the reason the failure can be fixed properly. The technical cause is narrow, known, and preventable. The reputational issue is broader: public confidence is affected when a standards body experiences a known control failure and its first explanation does not match the evidence readers can independently inspect.

Our opinion remains irrelevant beside the record. The archive captures, commits, workflow, current configuration, and source documentation are available for anyone to check. The appropriate standard is the same one that should apply to every security incident: state what happened, state what did not happen, state what remains unknown, then demonstrate that the control cannot fail in the same way again.

## Sources and reproducible checks  

- [Expected site capture — 21 September, 04:43:05 UTC](https://web.archive.org/web/20260921044305/https://api-security.owasp.org/)
- [Forced deployment commit 9ef4ea0](https://github.com/OWASP/API-Security/commit/9ef4ea0b867b99aa19485073cc846ba663a55220?ref=articles.akadata.co.uk)**Our opinion counts for squat. The public record is what matters.**
- [NOX-branded notice capture — 21 September, 15:20:33 UTC](https://web.archive.org/web/20260921152033/https://api-security.owasp.org/)
- [Commit adding the CNAME binding](https://github.com/OWASP/API-Security/commit/ed89451e41ebf965cab53e80e926f52064e6412d?ref=articles.akadata.co.uk)
- [Public deployment workflow](https://github.com/OWASP/API-Security/blob/master/.github/workflows/ci.yml?ref=articles.akadata.co.uk)
- [Later capture of the notice page — 21 September, 21:25:43 UTC](https://web.archive.org/web/20260921212543/https://api-security.owasp.org/)
- [Repair commit restoring the CNAME file](https://github.com/OWASP/API-Security/commit/3d6e4df271a6c3aea08dff375c90e022c91db171?ref=articles.akadata.co.uk)
- [GitHub Pages guidance on custom-domain takeovers](https://docs.github.com/en/pages/configuring-a-custom-domain-for-your-github-pages-site/troubleshooting-custom-domains-and-github-pages?ref=articles.akadata.co.uk)
- [OWASP Subdomain Takeover Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Subdomain%5FTakeover%5FPrevention%5FCheat%5FSheet.html?ref=articles.akadata.co.uk)
- [OWASP vulnerability disclosure route](https://owasp.org/security/?ref=articles.akadata.co.uk)

> Read our full offline report: <https://articles.akadata.co.uk/content/files/2026/09/OWASP%5FAPI%5FSecurity%5FSubdomain%5FTakeover%5FAssessment.docx>