Aunova · Greenblocks← Back to home

Security audit: aunova.ae

Published 27 July 2026 · scan of commit 47ddf73 · signed and timestamped · all audits

This is the record of an automated security scan of the aunova.ae source, published so that it can be checked rather than taken on trust. It is evidence, not an endorsement. The tool's own output, the exact commit it ran against, a signature and an independent timestamp are all published below, together with the commands to verify each of them. Aunova's position elsewhere is that a control is something you can prove ran, not something a document asserts; this page is that position applied to Aunova.

Read the result modestly. aunova.ae is a static marketing site: no accounts, no sessions, no server-side logic, no database, nothing to log in to. There is very little attack surface here, so a short findings list is roughly what the architecture predicts, and it is not evidence that Aunova writes unusually safe code. What this artifact demonstrates is the publishing pipeline itself — a scan whose scope, inputs and outputs anyone can inspect and check. That is the whole claim, and it is deliberately a small one.

What was scanned

Repository
The aunova.ae site source: an Astro static site deployed to Cloudflare Pages, with no server runtime and no API routes.
Commit scanned
47ddf73ed36a2dc5a7a18a13fb771b1675cf9b97
Files in scope
51
Files analysed
46, giving 90.2 % coverage
Analysis chunks
28
Tokens processed
674,899
Stages run
S1 to S9, detection only (--stop-after s9)
Stages not run
S10 and S11, the tool's automated remediation and validation stages

Stopping after stage 9 was deliberate. Stages 10 and 11 are the tool's fix mode: they edit source in the repository being scanned. Nothing on this page was written, changed or confirmed by the tool. Every fix described below was made by a person, and reviewed by a person, after reading the finding.

How it was run

Tool
Visa Vulnerability Agentic Harness (vvaharness), version 1.1.0, Apache-2.0. Source:github.com/visa/visa-vulnerability-agentic-harness
Model roles
All eight model roles this run recorded — autoexclude, preprocess, threatmodel, decompose, deepdive, verify, dedup and chain — ranclaude-sonnet-4-6 through the Claude CLI.
Config profile
default.yaml, sha256645a36d472fbc43d7b2b8806eea0dba708c51ec9a8b996ece9bbd1fac99e2b61
Started
2026-07-27T08:25:54Z
Ended
2026-07-27T08:51:21Z
Duration
1527 seconds
Exit code
0

Every value above is recorded in run_manifest.json, published unmodified below. That file is what makes this page checkable rather than decorative: it pins the tool version, the model configuration, the config hash and the commit, so the description here can be held against the run.

What was found

Three findings, all of them fixed in commit e442cc4 before this page was published. Nothing unpatched is disclosed here.

CWESeverityCVSSFileFindingDisposition
CWE-346Medium6.8astro.config.mjsDev server ran with Host-header validation disabledFixed — e442cc4
CWE-345Medium5.4src/pages/privacy/data-request.astroPrivacy-request form asserted identity checking without stating a procedureFixed — e442cc4
CWE-20Low3.1src/lib/sendDM.tsEmpty-string sentinel let a hostile relay abort a message deliveryFixed — e442cc4

1. CWE-346 — dev server ran without Host validation

Medium, CVSS 6.8 · CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:N/A:N· astro.config.mjs

The Vite dev server was configured with allowedHosts: true, which switches off Host-header validation and with it the server's DNS-rebinding protection. The setting existed so the dev server could be reached over a public cloudflared tunnel. Those two facts together are the problem: an internet-reachable dev server with no Host restriction exposes Vite's /@fs/ endpoint, which reads files from the project root.

This is developer-workstation configuration. It is not part of the deployed site — aunova.ae is static files on Cloudflare Pages with no Vite process running anywhere — so the site that visitors reach was never affected. Fixed by replacing true with an explicit allowlist,["localhost", ".local", ".trycloudflare.com"], which keeps the tunnel workflow and restores the check.

2. CWE-345 — privacy-request form claimed a check it did not describe

Medium, CVSS 5.4 · CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:L/A:N· src/pages/privacy/data-request.astro

The GDPR data-subject-request form submits by mailto:, so the email address in the body is simply whatever the sender typed. Nothing in the form proves the sender owns that address, and on a static site with no backend nothing in the page can. The page nevertheless told the reader that Aunova confirms the request is genuinely theirs, without stating any procedure. Asserting a control while describing none is the part that actually needed fixing.

The fix is procedural, not technical, and the page now says so. No backend was added: there is no confirmation token, no verification link and no server-side check. What exists instead is an operator process, written down and published so it can be held against us. Aunova replies only to the address named in the request, requires a confirmation from that same address before anything is actioned, and otherwise refuses the request and records the attempt. It is published atHow we confirm the request is yours and mirrored in the privacy policy.

The limit is worth stating plainly: a process is only as good as the person following it, and publishing it does not make it self-enforcing. What publishing does is make the standard specific enough that a failure to meet it is visible.

3. CWE-20 — empty sentinel matched by a relay-crafted message

Low, CVSS 3.1 · CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:N/I:N/A:L ·src/lib/sendDM.ts

The contact form's Nostr delivery code initialised authEventIdto the empty string and only assigned it a real value once a relay had sent an authentication challenge. In the window before that, a relay replying["OK", "", false, …] would match the empty sentinel and abort the delivery attempt. The consequence is a contact message that fails to send when a relay is hostile or broken; there is no disclosure, because the message body is encrypted in the browser either way. Fixed by initialising to a null sentinel and guarding on it explicitly before the comparison.

What this does not tell you

  • The findings are LLM-generated triage candidates, not the deterministic output of a static analyser. The same scan run twice need not produce the same set.
  • The tool publishes no precision or recall figures. There is no measured false-positive or false-negative rate to quote, so none is quoted here.
  • The run produced 11 raw candidate findings, of which 3 survived the tool's own adversarial verification stage; it reports that ratio as a "verification precision" of 27.3 %. That number describes how many candidates survived a second look. It is not a measure of accuracy: the other 8 were judged unsupported, not independently proven wrong.
  • Every finding on this page was read, reproduced and fixed by a person. Nothing was recorded as resolved on the model's own say-so.
  • Absence of further findings is not proof that no vulnerability exists. This was one tool, on one repository, at one commit, covering 46 of 51 files. It is not a penetration test and not an assurance engagement, and it did not examine the hosting, the DNS, the build pipeline or the dependency tree.

Verify it yourself

These are the files the scan and the signing produced. The reports and the manifest are published exactly as they were written, with nothing edited out.

  • report.sarif — the machine-readable finding set, unmodified.
  • report.md — the tool's own written report, unmodified.
  • run_manifest.json — tool version, model roles, config hash, target commit and timing.
  • bundle.sha256 — the hash manifest covering the files above.
  • bundle.sig.json — the signed Nostr event over that manifest. Its x tag is the SHA-256 of bundle.sha256.
  • bundle.ots — the OpenTimestamps proof over the same manifest.
  • VERIFY.md — the same three checks, carried inside the bundle itself.

Download the bundle into one directory and run these from inside it. They need sha256sum, jq,nak and theOpenTimestamps client.

# 1 — the published files are the ones that were hashed
sha256sum -c bundle.sha256

#     re-derive the manifest's own digest: the value that is signed and stamped
grep -v '^#' bundle.sha256 | sha256sum

# 2 — the hash manifest was signed by Aunova. All three checks must pass.
nak verify < bundle.sig.json     # silence means the id and signature are valid

[ "$(jq -r '.tags[]|select(.[0]=="x")|.[1]' bundle.sig.json)" \
  = "$(sha256sum bundle.sha256 | cut -d' ' -f1)" ] \
  && echo "digest OK" || echo "DIGEST MISMATCH"

[ "$(nak encode npub "$(jq -r .pubkey bundle.sig.json)")" \
  = "$(curl -fsSL https://aunova.ae/.well-known/aunova-signing.pub \
       | grep -oE 'npub1[02-9ac-hj-np-z]{58}' | head -1)" ] \
  && echo "signer OK" || echo "SIGNER MISMATCH"

# 3 — that signature existed by a date Aunova could not have chosen
ots verify -f bundle.sha256 bundle.ots

All three have to pass, and each one answers a different question. Check 1 only proves the bundle is internally consistent — anyone can produce a consistent bundle. Check 2 ties that manifest to a key Aunova publishes at/.well-known/aunova-signing.pub, which isnpub1my0e6x7fujteyrekx96pfzaqpw35k4g6f7djlsx0ahpfvptwknuspuhy4pand signs audit bundles only. Check 3 is the one that establishes a date. The signed event carries its own created_at, but a date a signer writes into its own message proves nothing; the OpenTimestamps proof published with this bundle anchors the manifest's hash to the Bitcoin blockchain instead, so the date rests on published proof of work and on no one's word, Aunova's included. If your copy of ots reports the attestation as not yet confirmed, ots upgrade bundle.ots pulls the completed proof down once the block carrying it has settled.

Attribution

This audit was produced with the Visa Vulnerability Agentic Harness (vvaharness), Copyright 2026 Visa, Inc., used under the Apache License, Version 2.0, a copy of which is available atapache.org/licenses/LICENSE-2.0. The tool depends on third-party software components which it does not redistribute; those dependencies and their licences are listed inTHIRD_PARTY_LICENSES.md in the tool's own repository.

Aunova ran the tool and Aunova is responsible for everything on this page. Naming the software is a factual statement about which program produced the output, and nothing more. The Apache licence covers the code, not the marks: Visa has had no involvement in this scan, its findings, its remediation or this website, and nothing here is a statement by Visa. The same applies to Anthropic, whose models the tool called.


Published 27 July 2026 and immutable. This artifact describes commit47ddf73 and nothing else; changes made to aunova.ae after that commit are outside it. Aunova re-scans quarterly, so the next scan is due on or before 27 October 2026 and will be published at its own dated path. This page then stays online unchanged and gains a link forward to its successor. Corrections are new versions that link back, never silent edits to this one.

Trust infrastructure for premium real estate.
PrivacyCookiesPrivacy request
Security audit: 27 July 2026 · signed ·view reportAunova Technologies Ltd · Dubai (DIFC)