Skip to content

Commit

Permalink
Merge pull request #1 from jgogstad/replace-with-redacted
Browse files Browse the repository at this point in the history
Add masked commands to history
  • Loading branch information
jgogstad authored Jun 19, 2021
2 parents 509b261 + 070e441 commit a3d949e
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 19 deletions.
71 changes: 57 additions & 14 deletions README.md
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:
Expand All @@ -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.
28 changes: 23 additions & 5 deletions passwordless-history.plugin.zsh
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
}

0 comments on commit a3d949e

Please sign in to comment.