Skip to content

SiteCMD 1.3.0

Choose a tag to compare

@github-actions github-actions released this 05 Sep 05:00
· 26 commits to main since this release
v1.3.0
0095ae9

Added

  • Scans can target a development server on your own network, such as
    http://192.168.1.40:8080/, a container by its service name in CI, or a
    machine on a tailnet. SiteCMD runs as you, on your machine, with your
    network, so a target you name reaches what you can already reach. Only the
    target you name gains that reach: a redirect, a stylesheet, a sitemap entry,
    or any other URL a fetched page chooses still reaches no further than the
    origin you asked for, and link-local addresses stay refused everywhere
    because cloud metadata answers there. The hidden browser keeps the narrower
    loopback boundary, so a private-network scan reports its browser measurements
    as unavailable.

Changed

  • The scan category labeled "Legal" is now "Privacy & Policies". Its checks
    observe what a page shows: whether a privacy notice, terms, accessibility
    statement, consent banner, or tracker is present, and how long a cookie
    lives. They do not determine whether a site meets a legal obligation, and
    every one of those findings already said so in its own words. The label now
    agrees with them, and the scales-of-justice icon that made the same claim
    without words is now a fingerprint. The category id is unchanged, so saved
    scans and issue history carry over untouched.
  • Confirmation dialogs for protected actions now name the action in the title
    bar, and the warning icon is reserved for actions that destroy data, revoke
    access, or disclose a secret. Saving an integration used to raise a warning
    triangle headed "Allow Protected Action"; it now reads "Save Integration"
    and asks the same question in the same words. The confirmation itself is
    unchanged, so storing a credential, configuring a webhook, or syncing a
    connected site still needs a native dialog that nothing inside the app can
    answer on your behalf.

Fixed

  • Web links, including Bing setup, open without an extra confirmation dialog.
  • Google integration setup stays on the selected service and no longer defaults
    to an unrelated Analytics property or Search Console site.
  • Google Analytics and Search Console connections include Google's required
    desktop client credential during sign-in and token refresh.
  • A Web Scan's score charged one defect more than once. Open Graph tags, form
    labels, the document language, heading structure, and page-level SEO markers
    are each graded by a Web Scan check and again by a polish signal, and both
    deductions landed even though the issue list already showed them as a single
    finding. A check that reports one row per occurrence, such as one per
    malformed Set-Cookie header, also deducted once per row while the dashboard
    score deducted once for the group. Both now charge a defect once, under the
    identity the issue list files it under, so a scan's score and the dashboard's
    agree. Category bars still report what each category observed, and scores on
    affected pages will read a little higher.
  • The app and the CLI disagreed about what could be scanned. The app refused a
    private address outright, while the CLI never checked a bare address at all
    and would scan one, yet refused the same machine named by hostname. Both now
    answer the same way, because the scanner validates its target itself rather
    than trusting each entry point to have done it.
  • A development server reached by its address on the local network was graded
    as a public production site. It earned a High "served over HTTP" finding
    measured against whatever answered port 443 at that address, and the custom
    404 page and CORS reflection checks had the same gap. Private network
    addresses now count as local, the way a localhost or .test hostname
    already did.
  • Web scans of pages that embed third-party iframes graded the wrong
    document. The hidden browser followed the iframe and measured that page
    instead, producing an accessibility failure, a load time, and a JavaScript
    error that belonged to somebody else's page. It now verifies which document
    it measured and reports the browser layer as unavailable rather than
    reporting a verdict about a different page. Every scan also reported one
    JavaScript error that was SiteCMD's own permission request, not the site's.
  • Half the open-redirect probes went unanswered on some sites, taking the
    redirect walk and the www check down with them, because the scan opened all
    of them at once and tripped its own HTTP/2 client's protection. Probes to a
    single origin are now bounded.
  • Time to first byte was measured while the scanner's own requests were in
    flight, so a server that accepts connections slowly was blamed for the
    scanner's retries.
  • A check that cannot reach a verdict now reports as skipped with the reason
    instead of guessing a warning. A rate-limited 404 probe, an unresolved www
    host, and a partial sitemap read all say what happened.
  • A site served only over HTTP now fails the HTTPS check instead of skipping
    it, so an unencrypted site no longer scores well on security.
  • Cross-page checks compared pages the scan never really reached: an error
    page could be reported as a duplicate title, and one page reached through
    two URLs was reported as a duplicate of itself.
  • Checks matched words inside comments and scripts. A commented-out heading
    counted as a heading, and the words "skip to" in a sentence passed for a
    skip link.
  • Sitemap dates written in the shorter standard form were all reported
    invalid, one site had all 1385 flagged. Cloudflare's email-protection link
    was counted as a broken link, and mail signing was reported missing on
    domains that sign through a provider the check never probed.
  • A published contact address in structured data was read as a leaked
    password, a form posting to the site's own subdomain was graded by neither
    of the two checks that cover it, and a site whose only analytics is
    cookieless was told it needs a cookie banner.
  • Code Scan reported findings for code that was not there: one rule matched
    the words "import" and "export" anywhere in a file, dependencies installed
    from GitHub were called registry mismatches, files a framework installs
    itself were graded as the project's own, and a structured-data block
    excused every raw-HTML sink in its file.
  • Coding agents reading SiteCMD through its MCP server could not see
    dependency findings that the score counts, and asking about one was refused
    even though the app itself accepts it.

Changed

  • Cancelling a scan now stops it. The code scan checks for cancellation
    before every file and between stages, the browser analysis abandons its
    wait and releases the hidden browser window, and a cancelled run saves
    nothing and reports nothing. Cancelling and starting again no longer leaves
    the old scan running underneath the new one.
  • Ordinary requests ask servers for compressed responses and cap the
    decompressed size, so registry metadata and other large downloads move less
    data. The measurement probes behind the performance checks still fetch raw
    bytes, so transfer sizes and compression headers stay true. Time to first
    byte is now measured the way a browser would see it, with compression
    negotiated, so that number can shift once for origins that compress on the
    fly.
  • The "Fix with" handoff to a coding agent no longer shows the system's Allow
    Protected Action dialog. It only opens the agent's app with the prompt
    staged in its composer; nothing runs until you send it there.
  • Web scans on Linux no longer run the browser layer, so Core Web Vitals and
    accessibility analysis report as unavailable there. The Linux webview gives
    SiteCMD no private-network subresource filter, and the app now refuses to
    load a page in it rather than expose the local network. Every other check
    still runs.

Fixed

  • Long scans no longer reload every open finding for the whole site after
    each page. The projection asks only for the routes the page covered.
  • Sitemap imports run in one transaction. A refused row keeps the previous
    list instead of leaving a partial or empty one, and the refresh reports the
    error instead of claiming success.
  • The code scan compiled its request-variable matchers once per evaluation
    instead of once per file, which took a 40 KB route file tens of seconds. It
    now takes milliseconds.
  • Multi-page scans download each shared stylesheet once per scan instead of
    once per page. A stylesheet that timed out is still retried on the next
    page; only a definite refusal is remembered for the rest of the scan.
  • Opening one scan's details fetches only that run's findings instead of
    every run in the execution.
  • The MCP server matched suppression patterns with a regex that a short
    pattern could stall for seconds. Matching now takes time linear in the
    pattern and path, and scan comparison loads history once instead of three
    times.
  • The dashboard kept one full code scan report per project in memory for the
    life of the app, including deleted projects. The cache is bounded and
    clears on deletion and when a newer scan lands.
  • The scan-scope picker, sitemap settings, and issue Locations lists page
    their rows the way the Issues list does, so a site with thousands of pages
    no longer mounts every row at once.
  • The startup bundle gate missed part of the eager graph and reported a false
    pass. It now walks every static import, including the boot stylesheet, and
    the page guide panel, command palette, scan summary, add-project, and
    telemetry consent overlays, and the scan completion handlers load on
    demand to keep startup under budget.
  • The scan progress percent no longer sprints, freezes, and leaps. It was
    mapped straight onto check counts, so ninety in-memory checks filled half
    the ring in the first second, the network-bound origin checks then held it
    flat for anything from one to thirteen seconds, then leapt to the end. One
    time-aware model now owns the number for the overlay ring, the jobs tray,
    and the system tray: every event sets a floor, the estimate drifts toward
    the end of the current phase between events, each step of a full scan fills
    its own ring, and the number never moves backward within a step.
  • The scan form offers accessibility analysis again. The axe-core pass is on
    by default for web scans, with a switch to skip it for a quicker run, and
    the first baseline scan of a new project includes it so later runs compare
    like for like. The option had been wired to a paid gate that no longer
    existed, so no desktop scan could run it.
  • Browser analysis now delivers Core Web Vitals, the browser build, and axe
    results again. The analyzer read every result back through the window
    title, which Tauri only updates from the page when asked, so each read
    silently timed out and every scan recorded the browser layer as having run
    with nothing to show for it.
  • Accessibility results and Core Web Vitals now cross from the scanned page in
    chunks. The platform truncates a document title to 1000 characters, so a
    full axe report written into one title never parsed and the pass timed out
    after 20 seconds; a Web Vitals payload carrying several JavaScript errors
    was lost the same way.
  • Accessibility analysis no longer takes fifteen seconds a page. The hidden
    analyzer window was timer-throttled as a background tab, on macOS by WebKit
    and on Windows by Chromium, and axe-core schedules its rule batches through
    timers. The analyzer now switches the throttle off before the page loads,
    so axe finishes in well under a second and the page under measurement runs
    at its normal speed.

Security

  • The hidden analyzer webview removes the WebRTC and WebTransport interfaces
    from every frame before a scanned page's scripts run, closing the one path a
    page had around the private-network subresource rules on macOS and Windows.
  • The PageSpeed API key is no longer captured as a tracing span field. No
    shipped build wrote it to a log file, because span fields are only forwarded
    at trace level and the app never logs at that level.

Verify

Installers and CLI archives are served from https://releases.sitecmd.com/v1.3.0/. The attached SHA256SUMS and SHA256SUMS.minisig are signed with the SiteCMD updater key; verification steps are in the README section https://github.com/brambleworks/SiteCMD/blob/main/README.md#verify-your-download.