-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Respect variable references when deciding whether to add to history
- Loading branch information
Showing
2 changed files
with
80 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,38 @@ | ||
# Passwordless ZSH history | ||
|
||
Keep passwords out of your ZSH history | ||
<!-- START doctoc generated TOC please keep comment here to allow auto update --> | ||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> | ||
|
||
ZSH will let you recover the previous command from history immediately after it has been run. After that it will not be added to history if it matches `HISTORY_EXCLUDE_PATTERN` | ||
|
||
- [Installation](#installation) | ||
- [Customization](#customization) | ||
|
||
<!-- END doctoc generated TOC please keep comment here to allow auto update --> | ||
|
||
This ZSH plugin masks secrets in your ZSH history | ||
|
||
Example: | ||
|
||
```bash | ||
❯ curl -H 'Authorization: Bearer eyJhbGciOiJIUzUxMiIsInR5c' https://example.com | ||
❯ curl -u foo:bar https://example.com | ||
❯ curl https://foo:[email protected] | ||
❯ AWS_SECRET_ACCESS_KEY=key aws s3 ls s3://example | ||
❯ export DB_PASSWORD=foo | ||
❯ history | tail | ||
1 curl -H 'Authorization: ...' https://example.com > /dev/null | ||
2 curl -u ... https://example.com > /dev/null | ||
3 curl https://[email protected] > /dev/null | ||
4 AWS_SECRET_ACCESS_KEY=... aws s3 ls s3://example | ||
5 export DB_PASSWORD=... | ||
``` | ||
|
||
ZSH will let you recover the previous command with secrets immediately after execution: | ||
|
||
```bash | ||
> curl http://username:[email protected]/foo | ||
> # <up-arrow> recovers command with password | ||
> # curl command is not available in history here | ||
> # <up-arrow> recovers command with password immediately after execution | ||
> # <up-arrow> recovers masked command here | ||
``` | ||
|
||
To exclude _any_ command from history, prefix with a space. It behaves the same as above: | ||
|
@@ -17,41 +42,59 @@ To exclude _any_ command from history, prefix with a space. It behaves the same | |
> # Not available here | ||
``` | ||
|
||
Control what secrets are catched by setting the environment variable `HISTORY_EXCLUDE_PATTERN`. If the pattern includes a single group, that group is substituted with `...`. The default `HISTORY_EXCLUDE_PATTERN` is | ||
|
||
```bash | ||
❯ echo $HISTORY_EXCLUDE_PATTERN | ||
^ |//([^/]+:[^/]+)@|KEY=([^ ]+)|TOKEN=([^ ]+)|BEARER=([^ ]+)|PASSWORD=([^ ]+)|Authorization: *([^'\"]+)|-us?e?r? ([^:]+:[^:]+) | ||
``` | ||
## Installation | ||
**Antibody** | ||
Using **Plain zsh** | ||
Download [passwordless-history.plugin.zsh](passwordless-history.plugin.zsh), then add to `.zshrc` | ||
``` | ||
antibody bundle jgogstad/passwordless-history | ||
source /path/to/passwordless-history.plugin.zsh | ||
``` | ||
**Antigen** | ||
Using [**Antibody**](https://getantibody.github.io) | ||
``` | ||
antigen bundle jgogstad/passwordless-history | ||
antibody bundle jgogstad/passwordless-history | ||
``` | ||
**Plain zsh** | ||
Using [**ZInit**](https://github.com/zdharma/zinit) | ||
Add to `.zshrc` | ||
Add the following to `.zshrc` | ||
```bash | ||
zinit light jgogstad/passwordless-history | ||
``` | ||
. /path/to/passwordless-history.plugin.zsh | ||
Using [**ZPlug**](https://github.com/zplug/zplug) | ||
Add the following to `.zshrc` | ||
```bash | ||
zplug 'jgogstad/passwordless-history' | ||
``` | ||
## Customization | ||
Default exclusion pattern is | ||
```bash | ||
> echo $HISTORY_EXCLUDE_PATTERN | ||
^ |password|//[^/]+:[^/]+@|(KEY|TOKEN|SECRET)=|Authorization: | ||
❯ echo $HISTORY_EXCLUDE_PATTERN | ||
^ |//([^/]+:[^/]+)@|KEY=([^ ]+)|TOKEN=([^ ]+)|BEARER=([^ ]+)|PASSWORD=([^ ]+)|Authorization: *([^'\"]+)|-us?e?r? ([^:]+:[^:]+) | ||
``` | ||
|
||
Overwrite variable to customize | ||
|
||
```bash | ||
> export HISTORY_EXCLUDE_PATTERN="^ykchalresp|$HISTORY_EXCLUDE_PATTERN" | ||
❯ export HISTORY_EXCLUDE_PATTERN="^ykchalresp|$HISTORY_EXCLUDE_PATTERN" | ||
``` | ||
|
||
The pattern is a regex and it's evaluated with zsh's `=~` operator using case insensitive evaluation. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,31 @@ | ||
# ZSH | ||
#!/bin/env zsh | ||
|
||
HISTORY_EXCLUDE_PATTERN='^ |password|//[^/]+:[^/]+@|(KEY|TOKEN|SECRET)=|Authorization: *[^ \$]' | ||
HISTORY_EXCLUDE_PATTERN='^ |//([^/]+:[^/]+)@|KEY=([^ ]+)|TOKEN=([^ ]+)|BEARER=([^ ]+)|PASSWORD=([^ ]+)|Authorization: *([^'"'"'\"]+)|-us?e?r? ([^:]+:[^:]+) ' | ||
|
||
# See | ||
# - https://zsh.sourceforge.io/Doc/Release/Functions.html for docs on zshaddhistory | ||
# - https://zsh.sourceforge.io/Doc/Release/Shell-Builtin-Commands.html for docs on print | ||
function zshaddhistory() { | ||
emulate -L zsh | ||
unsetopt case_match | ||
if ! [[ "$1" =~ $HISTORY_EXCLUDE_PATTERN ]] ; then | ||
print -Sr -- "${1%%$'\n'}" | ||
|
||
input="${1%%$'\n'}" | ||
[[ "$input" =~ "$HISTORY_EXCLUDE_PATTERN" ]] | ||
|
||
if [[ -z "$MATCH" ]]; then | ||
print -Sr -- "$input" | ||
else | ||
return 1 | ||
nonempty=($match) | ||
|
||
if [[ $#nonempty -gt 0 ]]; then | ||
for m in "$nonempty[@]"; do | ||
n="${m##[\"\']}" | ||
input="${input/${n%%[\"\']}/...}" | ||
done | ||
|
||
print -Sr -- "$input" | ||
fi | ||
return 1 | ||
unset match | ||
fi | ||
} |