Skip to content

Before you share a deploy log: what SchemaSmith masks

The deploy failed, you’ve read the log, and now someone else needs it — the ticket, the vendor, the teammate on the other side of the world. You drag the logs folder into the upload box. Do you know what’s in it?

Hey folks. I’m Forge Barrett, master of the Content Forge here at SchemaSmith.

Six modules taught you to read a log. This one is about handing it over: what SchemaSmith masks on its own, the secret it can’t recognize, the two settings that fix that, and the one file that keeps your real values on purpose. Let’s heat things up.

Every run writes its configuration and its script tokens near the top of Progress.log, so you can see exactly what a deploy ran with. The lab’s product carries five tokens, four of them secrets. Here’s what the log printed — the same on SQL Server, PostgreSQL, MySQL and MariaDB:

Product Script Tokens:
Region: us-east
DeployKey: dk-7f3a91c2
ReportingApiKey: ***
WebhookUrl: https://deploybot:***@hooks.shop.test/deploys
AuditDsn: Server=audit.shop.test;User Id=auditor;Password=***;
ProductName: Settings

Two kinds of masking are at work.

  • By name. A name containing Password, Pwd, Secret, ApiKey, Token, ConnectionString or Credential — any case — prints as ***. That’s ReportingApiKey.
  • By shape. Some values are secret whatever they’re called. A URL with a password in it loses the password and keeps the user, host and path. A Password= inside a connection string is stripped. That’s WebhookUrl and AuditDsn.

And then there’s DeployKey: dk-7f3a91c2, in clear. Key on its own isn’t a pattern. SchemaSmith masks what looks secret; it can’t know what your names mean. That’s not a bug to wait out — it’s the gap you close yourself.

Reading a long log by eye is how a secret gets through. Search it for the values you know:

Terminal window
grep -rl "dk-7f3a91c2" logs
logs/SchemaQuench - Progress.log
logs/SchemaQuench.0001/SchemaQuench - Progress.log

Two files, not one. Every run keeps a numbered copy of its logs in the same folder — SchemaQuench.0001, .0002 and on. Hold onto that; it matters in a minute.

The fix is one block in the settings file the deploy already uses:

"LogHygiene": {
"ScrubTokens": [ "DeployKey" ]
}

Deploy again and the token block reads DeployKey: ***. Search again:

logs/SchemaQuench.0001/SchemaQuench - Progress.log

The current log is clean. The copy from the earlier run isn’t. Fixing the setting fixes the next log, never the last one. So share the run, not the folder — or clear the folder and re-run before you attach it.

ScrubTokens names exact tokens. Its two siblings: ScrubPatterns adds patterns of your own ("*Salt*"), and AllowTokens lets a false positive back out when a name matches a pattern but holds nothing secret.

Note: the configuration echo prints this block as ScrubTokens: *** — the setting’s own name contains Token, so it masks itself (#577). Read the token block to confirm it worked.

The mistake everyone makes once: one value where a list belongs.

"LogHygiene": {
"ScrubTokens": "DeployKey"
}

The deploy exits 0 and tells you, in one line:

LogHygiene:ScrubTokens is a single value, not a list, and is ignored. Write it as [ "DeployKey" ].

Ignored means ignored — DeployKey is back in clear. A misspelled key gets the same treatment: "ScrubToken" logs LogHygiene:ScrubToken is not a setting and is ignored. The settings are LogTokens, ScrubTokens, ScrubPatterns and AllowTokens. That warning is the only signal, and an exit 0 buries it. If your pipeline should stop on a warning, run with --ExitNonZeroOnWarning: the same deploy exits 1. The switch never touches a failure code; it only refuses to call a warned run a clean 0.

On 2.7.x --ExitNonZeroOnWarning does not exist yet: the run logs a line starting Ignored - not recognized: --ExitNonZeroOnWarning and exits 0.

A product with hundreds of tokens turns the top of every log into a wall. "LogTokens": false folds the whole block into one line:

Product Script Tokens: (suppressed via LogHygiene.LogTokens=false)

No names, no values. The tokens still reach your scripts — the lab checks the rows its After script wrote.

Check yourself: Your settings file sets ScrubTokens to DeployKey as a single value, without the list brackets. The deploy exits 0, and you attach the log to a ticket. Is the deploy key in it?

Yes. A list setting written as a single value is ignored — the log says so in one line, LogHygiene:ScrubTokens is a single value, not a list, and is ignored. — so DeployKey falls back to the default rules, and Key alone matches none of them. Exit 0 didn’t mean the block worked; it meant the deploy did. Write it as [ "DeployKey" ], re-run, and search the current run’s log for the value itself before you attach it. If you want that warning to fail the pipeline instead of scrolling past, add --ExitNonZeroOnWarning.

Now the deploy fails. The lab’s broken variant rotates the reporting key and then writes to a table nobody added to the package. Exit 2, and the shape you know from Module 1:

Resolved SQL written to: ./artifacts\SchemaQuench - Failed 02_rotate_report_key localhost,11433.diag_hygiene.sql
Unable to quench '.\broken\Templates\Main\After Scripts\02_rotate_report_key.sql': Invalid object name 'key_rotation_log'.

That’s SQL Server on Windows (paths print with your system’s separator); the other engines name the same file with localhost and give their own “no such table” error. Search the logs and the artifacts for rk-55aa01be. The logs are clean. The artifact isn’t:

INSERT INTO dbo.app_setting (setting_name, setting_value) VALUES ('report_api_key', 'rk-55aa01be');

And its header says so: -- Contains expanded values — may be sensitive. Local debugging; scrub before sharing.

That’s on purpose. The artifact is the thing you paste into your client to re-run the failure exactly as the deploy ran it, and it can only do that with the real values. So the rule fits on one line: logs travel, artifacts stay on your machine.

Don’t reach for ScrubArtifacts to make one shareable. It swaps each secret for ***, which hides them, but '***' inside quotes is still valid SQL. Re-run that file and it writes *** into your table (#576). Masked is safe to read, not safe to run.

Check yourself: A teammate wants the failing SQL for a ticket, so they turn on ScrubArtifacts and attach the artifact. What's the risk?

The secrets are masked, but the file still runs. A value inside quotes becomes '***', which is valid SQL — so anyone who fixes the real error and re-runs the artifact writes *** where the key belonged. The artifact exists to be re-run with real values; that’s why it holds them. Keep it on the machine that produced it, attach the log once you’ve searched it, and describe the failing statement in the ticket instead of shipping the file.

Three checks, every time:

  1. Share the run, not the folder. Older runs’ copies don’t get cleaner when you fix a setting.
  2. Search for every secret you know — the values, not the names.
  3. Leave the artifacts behind. They hold real values by design.

Name it, search it, keep the artifact home.

You can walk into any failed deploy on SQL Server, PostgreSQL, MySQL or MariaDB, locate the phase from the progress log, read the artifact the engine left behind, name whose problem it is, pick the recovery that fits — and hand the log to the next person without handing over your secrets. For the masking rules in full, the configuration reference carries a Sensitive value masking section.


A good smith shows the work and keeps the recipe. The log is the work — it travels, and SchemaSmith takes the edge off it before it goes. The artifact is the recipe, real measures and all, and it stays at the bench. Know which one you’re handing over and you’ll never give away more than you meant to.

Found a secret that slipped through a log, or a name pattern you think SchemaSmith should know? Email me at forgebarrett@schemasmith.com — I read every one.

That’s Course 8. Thanks for forging through the whole thing with me.

Until then, may every log you hand over tell the whole story and keep every secret.

— Forge