Skip to content

Instantly share code, notes, and snippets.

@networkException
Last active October 23, 2020 23:32
Show Gist options
  • Save networkException/b1ccad6f338fe086db6f38031fb431a8 to your computer and use it in GitHub Desktop.
Save networkException/b1ccad6f338fe086db6f38031fb431a8 to your computer and use it in GitHub Desktop.
a spec for referencing entities in a keepass database

Introduction

The keepass implementation KeePassXC will soon support html and as such also anchors as well as other elements that allow a user to set a hyperlink. This spec describes a url subscheme for referencing or selecting various entities in a keepass database.

Originally this has been proposed on github. The issue contained a simple database structure that will be used for examples here as well:

For this example I'm using a simple database structure:

The entry "github" is nested inside the group "accounts".
In the advanced edit widget there is an additional
attribute called "backup codes".

Generic URL

As the keepass spec is going repurpose some sections in a generic url, it is important to also name those first.

https://max:[email protected]:8080/index.html?p1=A&p2=B#ressource
\___/   \_/ \____/ \_____________/ \__/\_________/ \_______/ \______/
  |      |     |          |         |      |           |         |
scheme   |  password     host      port   path       query    fragment
        user 

source: https://de.wikipedia.org/wiki/Uniform_Resource_Locator

Host

The host is again split up in parts, read from right to left. First there is the top or first level domain tld | 1ld (com in the example above, followed by the second level domain sld | 2ld (example) and so on.

KeePass URL

Scheme

The scheme will be static for all urls. It just indicates that the url references something related to keepass. Proposed are keepass and dbref.

Reference

General Case

The most basic function of a generic url is to specify the location of some data. In case of the keepass url this reference of an entity is most simply achived by using the host and path. To avoid ambiguity, both the type of entity referenced and the way it is referenced have to be specified.

Consider the following example:

keepass://entry.path/accounts/github

Key Value Name
scheme keepass
2ld entry referenceableEntityType
tld path referenceType
path /accounts/github reference
directory /accounts
file github (referencedEntity)

Reading the url from left to right makes clear what it references. The entry entity is referenced by the path /accounts/github. As the referenceType is a path, the generic url's file key even let's a reader quickly identify the entities name (github).

Attribute Case

An addition to the general reference is referencing an entry's attribute. This can be achived by using the userinfo section of a generic url.

keepass://[email protected]/accounts/github

Key Value Name
scheme keepass
userinfo Password (referencedEntity)
2ld entry referenceableEntityType (file)
tld path referenceType
path /accounts/github reference
directory /accounts
file github

In this case, the referenced Entity is not the entry github anymore, but it's attribute Password.

Option Case

Depending on the type of entity referenced by the path, an option might also change the referencedEntity. However, this option needs to come first, as it effects the newly set referencedEntity will be relevant for all following options. This is described in greater detail in reference case

Options

After successfully referencing an entity, there needs to be something the implementation should do with it. This is defined by the query string of a generic url.

General Case

An option can be represented by a key name and it's value type. For example, the notation foo: boolean would correspond to an url looking like this:

keepass://entry.path/accounts/github?foo=true

Key Value Name
scheme keepass
2ld entry referenceableEntityType
tld path referenceType
path /accounts/github reference
directory /accounts
file github (referencedEntity)
query foo=true options
foo true

Void Case

The notation <>: void would only accept an empty value. This can be used to run an action that doesn't require an input parameter.

Union Case

Furthermore it is also possible to allow multiple value types. For example, to make a parameter optional <>: <type> | void can be used.

Reference Case

Similar to the attribute case, there also is the possibility to modify the referencedEntity. Consider <widgetType>: string, with the widget type used here being plugin:

keepass://entry.path/accounts/github?plugin=_LAST_MODIFIED

Key Value Name
scheme keepass
2ld entry referenceableEntityType (file)
tld path referenceType
path /accounts/github reference
directory /accounts
file github
query plugin=_LAST_MODIFIED options
plugin _LAST_MODIFIED (referencedEntity)

Any following options again use the general case.

A more extreme variant which gets pointed out seperately is the entityType database. If an entry in the database should be the referencedEntity, it needs to be defined in the options.

keepass://database.path/home/anon/database.kdbx/?entry.path=/accounts/github

Key Value Name
scheme keepass
2ld database referenceableEntityType (file)
tld path referenceType (file)
path /home/anon/database.kdbx reference
directory /home/anon
file database.kdbx
query entry.path=/accounts/github options
entry.path /accounts/github
2ld (option) entry referenceableEntityType (file (option))
tld (option) path referenceType (file (option))
path (option) /accounts/github
directory (option) /accounts
file (option) github (referencedEntity)

As in this case the path is part of a query value, it doesn't need to be url encoded. The attribute case would, as well as additional options, also apply to the entry in this case.

Notations

If no options are specified in the url, the defaults to option will be used.

  • Database

    defaults to showing the root group

  • Group

    defaults to selecting the group in it's parent group. If root, defaults to edit

    • edit: void If set, opens the group instead of selecting it in it's enclosing parent group (ignore if root)
  • Entry

    defaults to selecting the entry in it's parent group

    • edit: widgetType | void If an edit widget of the entry should be opened instead of showing it in the parent group. If no value or an empty value gets specified, the default widgetType will be used.
    • <fieldType>: string References a field in an entry. See field type for possible keys and reference case for reference behavior.
    • history: historyReference References a history item of the entry. See entry option case for reference behavior.
    • autotype: void Perform autotype for the entry
    • clipboard: void | copyableType Copies the password to the clipboard. If no value or an empty value gets specified, the default copyableType will be used.
  • TextArea

    defaults to line=0; column=0; highlightLine=false;

    • line: uint A line of text to jump to.
    • highlightLine: boolean If the line should be highlighted (ignore if line not set).
    • column: uint A column the curser should jump to (line is 0 if not specified).
  • File

    defaults to selection in the parent widget

  • Property

    defaults to selection in the parent widget

Types

Possible types to be used in notations.

  • PrimitiveType

    • string An url escaped string
    • boolean true or false
    • uint A positive number (including 0)
  • ReferenceableEntityType

    db | database, group, entry

  • EntityType extends ReferenceableEntityType

    textArea, file

  • ReferenceType

    • path A path seperated by /.
    • uuid The id of an entity.
  • FieldType

    • attribute: textArea A user defined attribute.
    • attachment: file A file attachment.
    • plugin: property A the key of an entry in plugin data.
  • WidgetType

    defaults to main

    • main The main widget of an entry, containing title, username, password and so on.
    • advanced The advanced edit widget of an entry, (at least in KeePass XC) containing additional attributes and attachments.
    • history The history widget showing previous versions of an entry.
  • HistoryReference

    Either a timestamp or an index in the entry's history. Note that the timestamp used might be different between database implementations. Each implementation should at least support the format in which it is displaying the timestamp in the application.

    01.09.20 18:43, 0 (current version, probably should not open a preview), 1 (one version ago)

  • CopyableType

    defaults to password

    • username Copies the username
    • password Copies the password
    • url Copies the url

Examples

<a href="keepass://entry.path/accounts/github/">Opens the entry's parent group and focuses "github"</a>
<a href="keepass://entry.uuid/21ea1457b4ec418496d1811b0a9b67cb/">Opens the entry's parent group and focuses "github"</a>

<a href="keepass://group.path/accounts/">Shows the groups parent group and focuses "accounts"</a>
<a href="keepass://group.path/accounts?edit">Opens the "accounts" group</a>

<a href="keepass://entry.path/accounts/github">Opens the entry's parent group and focuses "github"</a>

<a href="keepass://entry.path/accounts/github?edit">Opens the main edit widget of "github"</a>
<a href="keepass://entry.path/accounts/github?edit=main">Opens the main edit widget of "github"</a>

<a href="keepass://entry.path/accounts/github?edit=advanced">Opens the advanced edit widget of "github"</a>
<a href="keepass://entry.path/accounts/github?edit=history">Opens the history edit widget of "github"</a>

<a href="keepass://backup%[email protected]/accounts/github">Opens the advanced edit widget of "github" and selects the "backup codes" attribute</a>
<a href="keepass://entry.path/accounts/github?attribute=backup%20codes">Opens the advanced edit widget of "github" and selects the "backup codes" attribute</a>

<a href="keepass://entry.path/root/accounts/github?attribute=Notes&line=2&column=4">Some line and column in the notes of "github"</a>
<a href="keepass://[email protected]/root/accounts/github?line=2&column=4">Some line and column in the notes of "github"</a>

<a href="dbref://entry.uuid/21ea1457b4ec418496d1811b0a9b67cb?plugin=_LAST_MODIFIED">Hightlights the "_LAST_MODIFIED" key value pair in the plugin data widget</a>

<a href="dbref://[email protected]/34eb1447b7ec218446d1451b0c9b49a1?entry.uuid=21ea1457b4ec418496d1811b0a9b67cb">
    Go to open database with uuid 34eb1447b7ec218446d1451b0c9b49a1 open the entry with
    uuid 21ea1457b4ec418496d1811b0a9b67cb and highlight it's password
</a>

<a href="dbref://[email protected]/34eb1447b7ec218446d1451b0c9b49a1?entry.path=/accounts/github/">
    Go to open database with uuid 34eb1447b7ec218446d1451b0c9b49a1 open the entry with the path /accounts/github/ and highlight it's password
</a>

<a href="dbref://db.uuid/34eb1447b7ec218446d1451b0c9b49a1?entry.path=/accounts/github/&attribute=Password">
    Go to open database with uuid 34eb1447b7ec218446d1451b0c9b49a1 open the entry with the path /accounts/github/ and highlight it's password
</a>

<a href="dbref://db.uuid/34eb1447b7ec218446d1451b0c9b49a1?entry.path=/accounts/github/&attachment=notes.txt">
    Go to open database with uuid 34eb1447b7ec218446d1451b0c9b49a1 open the entry with the path /accounts/github/ and highlight a file named "notes.txt"
</a>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment