PAM - help

pam

personal account manager webapp

Metadata

The meta data in the table is populated during the build process when the on-line help is generated.

Field Value
Author Joe Linoff
Copyright (©) 2022
License MIT Open Source
Version 1.1.20
Bootstrap Version 5.3.6
Build 2025-06-16 19:03:39 -0700
GitCommitId 4619ff9
GitBranch main
project https://github.com/jlinoff/pam
webapp https://jlinoff.github.io/pam/www/
help https://jlinoff.github.io/pam/www/help/
Table of Contents

Introduction

PAM or Personal Account Manager is a free and open source, single page web application that is designed to help you conveniently and securely manage your confidential information like passwords inside the secure context of your web browser as dynamically configurable records that can be searched without having to rely on services from a third party server because they are stored in a file that you control either on your local device or on a cloud based file server.

The PAM file is encrypted both in transit and when stored so the contents are safe from hackers if the file was stolen assuming, of course, that the password you used to encrypt it was strong.

The PAM file flow is shown in the figure below. Note that the save device and the load device could be the same device.

pam-file-flow

You can access PAM from your own secure web server (including localhost) or from the public github.io server. In either case, once the application is loaded into your browser or run as a local web app (PWA) there is no other communication with the web server which you can verify by monitoring outbound network traffic.

In addition, PAM is designed to be mobile friendly so you can access it from your laptop browser as well as your mobile phone and tablet.

It looks something like this on my iphone in dark mode for the fictitious example records that are provided by PAM to practice with, as described in the Load File section later on.

iphone-screenshot-light-mode

And something like this in light mode.

iphone-screenshot-dark-mode

At the bottom left of the screen there is a button that allows you to toggle between light and dark mode. It looks like a sun (switch to light) in dark mode: clipboard and like a moon (switch to dark) in light mode: clipboard.

Dark and light mode examples will be intermixed throughout this document.

The records appear as accordion entries that expand when you click on them as shown below.

google-account-example

Once the record is expanded you simply click on the clipboard clipboard icon associated with the record field you are interested in (like the password) to copy its value to the system clipboard so that it can then be pasted them into the appropriate login field. You can click on the eye eye icon to see the password in plaintext. By default all record fields containing sensitive information,like passwords, are masked so that a casual observer cannot see it.

You can even include images as shown in this example which is also provided by PAM to practice with and, like the examples above, is also described in the Load File section later on.

ice-cream-sundae-example

There are other features like memorable password generation and customized record fields that are described in the documentation below.

Please note that this is not the first tool I have written to manage passwords but it is meant to be the last. If you are interested in what motivated me to create yet another tool, see the Security Considerations and Reasons to consider using PAM. If you are interested in the genesis of PAM and the stories of its predecessors, see the History section.

I hope that you also find useful in some way.

Overview

PAM is a pretty simple application. It is basically a record editor that runs in your browser that allows you to create records with interesting information that can then be stored and retrieved in a secure way.

Reasons to not use PAM

This section talks about why you may not need or want to use PAM.

Reason 1: Do Not Need It

It is very reasonable to ask yourself why, if PAM is like an editor, you can’t simply just use something like an Excel spreadsheet or a text file editor or keep passwords on a sheet of paper or use one of the many commercially available password managers?

That is an excellent question. The answer is that you can and, if you are already using an Excel spreadsheet or a text file editor or a sheet of paper or a password management service or any other method that works for you, you should.

Reason 2: Too Complex

Even if you do not already have a method for managing passwords PAM may not be the right choice. PAM requires that you understand a bit about HTML input and textarea elements which may be confusing. Also the PAM user interface (UI) and record data model may be confusing or hard to understand and use because I am not a UI programmer.

The bottom line is that I wrote PAM to provide some features I wanted and to address some concerns I had with existing approaches. Those features and concerns are discussed in the next section to help you understand my reasoning so that you can decide whether any of them are important to you. If you don’t care about the features and the concerns that bother me, there is no reason to use this tool.

Reasons to consider using PAM

This section presents the nine primary reasons that motivated me to develop PAM. They are provided to to help you determine whether PAM might be interesting to you.

Reason 1: No Client Server Communications

PAM is a single page web application (SPA) that has no backend which means that it never communicates with an external site which protects it from some types of cyber attacks as detailed in the Security Considerations section.

Reason 2: Record Model

In PAM, information is organized into files composed of records that each have a unique title and are, in turn, composed of fields that have a name, a type and a value. This approach is similar to organizing information using index cards or a rolodex.

Following the index card analogy a little further, we can use a simple example to understand the record model a bit better.

A recipe would be something you might store on an index card. Each recipe could be a single record that might contain the title (the name of the recipe), the ingredients (a field) and the instructions (another field).

Simple Recipe Record

So what would a simple dessert recipe look like as a in PAM record? Well, if you had a simple dessert recipe like this written on a card with an attached picture.

ice-cream-sundae

Ice Cream Sundae

ingredients
1. 3 scoops vanilla ice cream
2. 1 banana (sliced up)
3. chocolate sauce
4. (optional) nuts
5. (optional) Maraschino cherry
6. whipped cream

instructions
1. put ice cream in bowl
2. add slices of banana
3. add nutes
4. pour chocolate on top
5. add whip cream
6. put the cherry on top.

It would look like this when you create it in PAM.

ice-cream-sundae-example

It would look like this when you view it in PAM in edit mode.

ice-cream-sundae-example

In this recipe record, the title is "Ice Cream Sundae" and the two fields ingredients and instructions contain the multiline (textarea) descriptions of what the ingredients and instructions are for this specific recipe. And, finally, there is an html field that contains the image.

Note that the record field names ingredients and instructions used in this example are custom field names. They are not available by default. The html field is a default field.

Custom fields can be created by adding new fields to the default fields defined in the preferences so they are available all of the time.

For this example I created two new textarea fields named ingredients and instructions so that users could enter multiple lines and removed all of the other default fields except the html field because they were not needed. I kept the default html field because I wanted to be able add pictures to the recipes. Here is what the preferences look like after the modifications were made.

default

Simple Account Record

Of course, there are many other types of records that might be interesting to store in PAM that can use the default record fields as is. See the Fields section for a description of the default records and their types.

One common one is a record for each account that you need to login into where you information about how to login is stored so you don’t have to remember it.

Such an account record would have, at a minimum, the web address (URL), the login name and the password of the account.

Note that this simplified example is only meant to show the basic idea of importance of supporting record formats that are different than recipes. For a real account record you would probably want to add additional fields like an email address or a notes field.

Here is what the simple account record would look like.

google-account-example

Note that the password is hidden in the example above. PAM always hides the contents of passwords by default.

Record Model Summary

Both records look quite different. Recipes records have fields for ingredients and instructions whereas account records have fields for the url, login and password. However, in both cases they have the same basic structure: a title and a set of fields that are relevant to recipes or accounts.

You could easily imagine defining other records that contain information for other topics like books read or unidentified aerial phenomena or bird watching which would undoubtedly require different fields. The idea of topics is dicussed in more detail in the Topics section.

In my view, this approach of using records composed of fields does a better job of representing this type of information than a spreadsheet or a text file.

Reason 3: Searching

PAM allows you to search records by their title or their field names and values. It also filters out the records that don’t match to make it easier to see the matching records visually.

The availability of fast interactive searching makes finding records easy.

This is what search/filtering looks like for all example records that contain a g in them. Note that, by default, search operations are case insensitive but that can be changed in the preferences.

search-g

Note that regular expressions can be used as well as shown in the example below that looks for records that start with g.

search-g-re

See Search for more details.

Reason 4: Automatic Password Generation

I always find it hard to come up with passwords in the spur of the moment so PAM was built with the ability to automatically generate passwords.

Of course almost all browsers and password tools provide this same capability nowadays, but they tend to generate secure, cryptic, hard to memorize passwords which is perfectly fine for passwords for most accounts.

But there are a cases when you need a password that must be typed in manually like the login password for a computer that does not use biometric scanning or a key FOB. In those cases it is beneficial to have a password that is secure, easy to remember and easy to type because you cannot access a password management system before you login.

I call passwords of this type memorable passwords. They are composed of common lower case English words with an optional prefix, an optional separator between each word and an optional suffix.

Often, the prefix and suffix are used to guarantee that the password contains the correct mix of characters that the authentication system requires, like, at least one capital letter, at least one digit and at least one special character.

To make these concepts a bit clearer, here are examples of a cryptic and a memorable password.

cryptic Rf5NaR7LH2LbZMRhkPCfeG8
memorable A1/health/mpegs/hopes!!

In this example, the memorable password word separator is "/", the prefix is "A1/" (capital letter and digit) and the suffix is "!!" (special characters).

To help with this, PAM was built with the ability to generate cryptic and memorable passwords.

For more detailed information about password generation in PAM see the Password Fields section.

Reason 5: File Based Storage

PAM uses files to load and store the record data.

Using a file means that the user does not have to rely on the cybersecurity infrastructure of a company running a web server and storing your data at their site or another third party site. This was alluded in Reason 1: No Client Server Communications but that is not the only advantage of using files.

A PAM file is composed of a set of records. Any records you like. You can use a single file for all of your records or you can have multiple files where each file contains records that are somehow related like records of recipes or book reviews or my favorite species of Euglena.

What this means is that you can group records associated by a topic in different files to make them easier to organize and find. This ability to organize files around topics is the other reason that I prefer the file based storage model.

For a more detailed discussion about how the user controls the organization of the records and fields in a file see the Reason 2: Record Model section of this document.

As a side note, I store my personal PAM record files in Apple iCloud which is one of many cloud based storage services like Dropbox, Google Drive and Microsoft OneDrive.

For files I want to share with other folks, I use Google Drive to store the file and then share it.

When properly configured all of these storage services store the PAM record file in the cloud so that it is available to anyone who knows the file password as long as their laptop, phone or tablet is authorized to access the storage service.

Of course you could simply load and save the data to a local file but that might restrict your ability to access to it from other devices (like mobile phones or tables). Not only that but you would have to be very diligent about keeping it backed up so that you would not lose data if the local file was corrupted or lost.

Reason 6: Secure Context Encryption

When records are stored in a PAM file they can be encrypted using a password. The password is then used by an NIST certified, symmetric encryption algorithm: AES-256-CBC to encode the records.

Using a certified encryption algorithm provides a strong security guarantee which means, that if an encrypted PAM file is stolen, the record data is considered safe from hackers trying to crack the contents if a strong password was used.

Passwords like secret or password123 or any other password that can be found in freely available password dictionaries like the Kali password dictionary are not strong and will not protect your data because they are easy to guess.

Always use a strong password to make it hard to guess. Typically a strong password would have at least 20 characters would not include any personally identifiable information (PII) like your name, birth date or address. Also never, ever use the same password for two different sites. This is to protect you from hackers if a site you use to is attacked and your password is stolen.

I recommend reading NIST Password Guidelines for more information about how to create strong passwords.

As an interesting aside, note that AES-256-CBC algorithm is considered to be reasonably resistant to quantum attacks as discussed in the literature. For example, here is one relevant exchange from a crypto.stackexchange.com discussion.

PAM encryption and decryption operations are provided by and run inside the secure context of the browser. This is the same secure context used for accessing sites securely for transactions, like your bank. In practice this means that you must access PAM from an HTTPS site.

The safety and security of secure context operations is taken very seriously by the internet standards organization and the organizations that develop the major browsers.

You can read more about secure contexts here.

Reason 7: Hiding Passwords from Casual Observers

Passwords and other secrets are automatically hidden on the screen (displayed as asterisks) so that someone looking over your shoulder cannot read them unless you choose to make them visible. You can read more about why this is beneficial in the Security Considerations section.

This is the default hidden view of a password. You can see that the password value is all asterisks.

password-hidden

This is the same view of a password when it is not hidden. You can now see the password value.

password-shown

Reason 8: Access from mobile devices

The record files can be accessed from mobile devices so the user has access to the records anywhere as described in the Reason 5: File Based Storage but that does not necessarily imply that the interface is mobile friendly.

What makes PAM mobile friendly is that it is implemented using the bootstrap-5 library to make the interface work better in the browsers present on mobile devices.

Reason 9: FOSS

Last but not least, one compelling reason to try PAM is that it is free and open source software (FOSS) so you can try it without any obligation or cost. You can also help find and fix bugs or improve the UI.

Records

Records composed of fields are a key concept in PAM as described in Reason 2: Record Model.

This section talks about how records are presented in PAM using an example with seven records that contain confidential information for Amazon, Email, Facebook, Github, Google, Netflix and Stack Exchange fictional accounts from the Load File example.

See the Create New Record section for details about how to create records and the Topics and Fields sections for more details about their contents.

Unexpanded View of all Records

We start with the unexpanded view of all records as shown below.

example-records

PAM presents the records as an accordion. Each record is one entry in the accordion that you can expand to view the record fields or delete, clone or edit edit the record.

To get the information for an account you click or tap the button.

At the top of the screen is the search bar and, at the far right, the menu.

At the bottom of the screen is a status bar that shows status messages.

Expanded View of a Record

Once you click on or tap a record it expands as shown below where the Facebook record was tapped.

record-expanded

You can see that there are three fields in the record: url, login and password, next to each field there is a icon that looks like a clipboard clipboard.

record-expanded

If you click or tap the clipboard icon, the field contents will be copied to the clipboard so that you can paste them into a login dialogue.

In addition to the clipboard icon there is another icon that looks like an eye eye that shows up for password field. If you click or tap it, the password will be shown in plaintext and the icon will change to an eye with a slash through it eye-slash. By default all passwords are hidden so that they are not visible to casual observers. Click or tap it again to re-hide the password. Passwords are correctly copied to the clipboard at all times even when the password is hidden.

In addition there are three buttons at the bottom trash Delete to delete the record, files Clone to clone the record and pencil-square Edit to edit the record fields.

As shown below.

record-expanded

The fields in records are completely customizable when you select the "Edit" option.

Fields are added to the record by selecting a new field from the "New Record" drop down menu as shown below for the "Facebook" record but these fields can also be changed. See the Custom Fields and Field Types sections for details.

record-expanded

Fields are modified in the record by editing them directly and they are deleted from the record by clicking on the icon.

record-expanded

Topics

Topics define how records are related. They provide a convenient abstraction for organizing related records in files. Topics are completely arbitrary. For example a topic could be something like recipes or accounts or unidentified aerial phenomena or my favorite cryptography algorithms or green things.

One way to use topics is to keep records related by a topic in separate files. For example, you could define a recipes.txt file for all of your recipe records (topic: recipes or stuff to cook) and an accounts.txt for your account records (topic: accounts).

Or, you could completely disregard organizing by topics and put all of your records into a single file like myrecords.txt.

Note the use of the .txt extension in the previous paragraphs. Although the .pam file extension is supported for record files and it works on laptops. It does not always work on mobile devices so a records file named myrecords.pam might not be readable by the mobile browser. Thus, I recommend using the .txt for all record files for maximum portability.

Fields

Records are composed of fields. Each field has a unique name, a type and a value.

The field name is arbitrary and is meant to describes how the data in the field is used. For example, an ingredients field would indicate that the value is a list of ingredients and a number field would indicate that the value is a number. An example of a field name might be mobile phone.

The field type explicitly describes the type of data that field holds like a number or a phone or an email. Types are built in and strictly enforced by javascript.

An example of the difference between a name and a type would be a field named mobile of type phone. The name describes how it is used whereas the type describes what the input type is which, in turn, dictates what user inputs are acceptable. A description of each built in record field type can be found in the Field Types section.

The field value is the unique value for the field in an individual record that is set when a field is created or edited. For example, an field named email of type email could have a value wombat@foo.io the name and the type could be the same for all records that had an email field but the value would vary.

The default record fields are the fields that are available in the "New Field" pull down menu when a record is created or edited. They are defined in the Preferences section and they are stored in each records file along with the records so each records file can have different default fields.

For example a file of recipe records would probably want fields of type textarea named ingredients and instructions but a file of books read records probably would not. Instead it might want text fields named author and publisher along with, possibly, a field of type number named copyright.

See the Record Fields section for details about how to add or modify the default record fields in the preferences dialogue.

There is a second more obscure way to define field names. You can change field names when you create or edit an individual record by setting the Enable Editable Field Name preference.

This capability is not enabled by default to avoid confusion between the name input and the value input as shown below. Normally only the value input is shown.

Typically there is no reason to change record field names on a per record basis. It is better to add the new record fields to the default list in the preferences.

change-field-name

Field Types

Record field types define the type of each field that you define for a record. They are based on HTML input element types except for the textarea type which is a HTML textarea element that is displayed as preformatted text (<pre></pre>) and the html type which is also a HTML textarea type but is displayed as raw HTML so it can be used for inserting images. They are presented below as simple types regardless of the underlying HTML element to avoid unnecessary complexity.

You can change, add or delete record field names here if you wish to customize the user experience but you cannot change the built in types. For example, you change the record field name note from a textarea field to a text but there is no way to add a new built in type to the drop down list from the user interface.

These are the default field definitions.

default

The table below presents a brief overview of the default record fields and their associated built in types and when to use them. You can search the web for more details about HTML input types.

Type Usage
datetime-local A datetime text string. Use it if you only want to accept a datetime value. A typical usage might be the date that you finished reading a book.
email An email text string. Use it if you only want to accept an email value. A typical usage might be the email address of a contact.
html Textarea data that is rendered directly as HTML. A typical usage might be to reference an image or to display formatted text.
number A numeric text string. Use it if you only want to accept an number value. A typical usage might be a measurement like height or width or any other numeric value.
password A secret text string that is normally displayed as asterisks (****) with an eye (eye) button that can be clicked or tapped to show the value.
phone A phone number text string. Use it if you only want to accept a phone number value. A typical usage might be a mobile phone number.
text A string, like a name or keyword. You can use this for any text but it is especially useful when a field can be multiple types like an email or a name. A typical usage might be a login name where the value might be a name like wiley or an email like wcoyote@acme.io or a number like 12345678.
textarea A multi-line text box. A typical usage might be a note or a list of recipe ingredients.
url A text string that is a uniform resource locator (URL). Use it if you only want to accept a URL value. A typical usage might be the path to an account like https://google.com
username A username. This may be slightly different than a login because a login could be an email address but, in general, it probably makes more sense to user login rather than username.

Remember that the types were not made up by me, they were taken directly from input element description here, the separate textarea element is described here.

Custom Fields

It is oftentimes the case that all of the default record fields are not needed for the records you are managing or you may want to define new, custom fields that are more intuitive for your records. This section shows you how to do that.

Here is an example that shows a recipe record with ingredients and instructions fields.

ice-cream-sundae-example

Here is what the preferences look like after ingredients and instructions record fields have been added and the previous default record fields other than html have been pruned out.

ice-cream-sundae-example-prefs

Here is an example that shows an account record with url, login and password record fields.

google-account-example

Here is what the preferences look like with the other fields pruned out. The url, login and password record fields are part of the default.

google-account-example-prefs

This is what they will look like in the "New Record" pull down menu when creating or editing a record.

new-record-field-1-select

Password Fields

Password fields are a special case for the following three reasons.

First, they provide a generator that allows you to automatically create passwords at the click or tap of a button. For information about preferences that can be used to customize password generation see Password Preferences

Second, they always hide the value by default so that it can be seen by someone observing your screen.

And, finally, because they provide the ability to generate two different types of passwords: cryptic and memorable.

Cryptic Passwords

Cryptic passwords consist of letters, digits and special characters.

Here is an example: 'N5yAb!XfGa3vELPsK95K4/AAz8mts'.

Cryptic passwords tend to be hard to memorize for most people.

They are perfect for cases where you don’t have to type the password in because they are hard to crack.

Memorable Passwords

Memorable passwords are used to define passwords that must be typed in manually, as described in the Reason 4: Automatic Password Generation section which means that it is important that they are secure, easy to type and to remember.

They are composed of common lower case English words with an optional prefix, an optional separator between each word and an optional suffix. Often, the prefix and suffix are used to guarantee that the password contains the correct mix of characters that the authentication system requires, like, at least one capital letter, at least one digit and at least one special character.

The security rationale for memorable passwords is described in this article: The logic behind three random words.

Here is an example: 'Z0/rebates/restructuring/jamaica??' where the prefix is 'Z0/', the separator is '/' and the suffix is '??'.

Memorable passwords tend to be easier to memorize than cryptic passwords for most people.

Hidden Password Representation

Here is an example that shows a password in its standard hidden form.

record-expanded

To make the password visible, click or tap on the eye icon.

The password can be copied to the clipboard when it is hidden by clicking on the clipboard icon.

Visible Password Representation

Here is an example that shows a password in its visible hidden form.

record-expanded-password

The password can be copied to the clipboard by clicking on the clipboard icon.

To hide the password, click or tap on the eye icon.

Password Generator

This is what the password field dialogue looks like with no generator.

password-no-generator

When you click or tap on the icon, cryptic and memorable passwords are generated and the password generator dialogue appears.

password-generator

It always generates five memorable passwords to provide choices. I found that more useful than the original implementation which only had a single choice.

The decision to present five memorable passwords was completely arbitrary but it seems to work well enough for my needs and can easily be changed.

This is what the password generator looks like with annotations.

password-generator-annotated

If you click or tap on the icon a second time, new passwords will be generated.

You must click or tap on the icon to close the dialogue.

I chose this approach because I wanted the icon to be used to generate new passwords.

In retrospect, that choice may not have been the most intuitive way to implement closing the generator dialogue it but it works well enough and can easily be changed if it turns out to be too cumbersome.

To choose a generated password simply click or tap on it and it will be added to the field value.

See the Password Preferences section about how to define the prefix and suffixes for memorable passwords.

Layout

PAM is a simple single page web application (SPA). It consists of three basic parts: the menu and search section, the records section and the status section.

It looks something like this

menu-bar

The top section that contains a search input and a menu.

PAM allows you to search records by their title or their field names and values to filter out records that do not match the search pattern. This is extremely useful when the number of records grows.

The search function at the top left supports case insensitive searches and regular expressions to make it easier to find records.

This can be very helpful for finding out where old passwords and obsolete accounts are still being used.

Here is the made up list of account records from the Load Files example:

pam-search

Here is the same list after filtering for those whose titles contain the letter "g". Note that searches are case insensitive but you can change that by unsetting the Case Insensitive Searches preference.

pam-search-g

To filter only those that start with "g" you would use this regular expression search term instead: "^g". which would result in only two records found.

For more information about regular expression syntax see the documentation for Javascript Regular Expressions.

For more information about how you control the all of the available search options see the Search Preferences section.

The menu at the top right is the control center for the application it has a number of options as you can see below. This is what it looks like.

menu

As you can see, there are seven menu options:

  1. About
  2. Preferences
  3. New Record
  4. Clear Records
  5. Load File
  6. Save File
  7. Help.

Click or tap on the  About entry to see information about the app. See the About section for more details.

Click or tap on the  Preferences entry to see the preferences dialogue which allows you to customize some of the app behavior. There is a lot of stuff so you might want to read the Preferences section before trying it.

Click or tap on the  New Record entry to create a new record. See the Create New Record section for more details.

Click or tap on the  Clear Records entry to delete all of the records. This is useful for times when you want to create a new collection of records that is saved in a separate file. For example, if you wanted to create a collection personal accounts in one file and a collection shared accounts for a group of folks (like a development team sharing AWS accounts).

Click or tap on the  Load File entry to load a records file. See the Load File section for more details.

Click or tap on the  Save File entry to save all of the records to a file. See the Save File section for more details.

Click or tap on the  Help entry to see this help message.

Records Section

Underneath the top level bar, in the middle, is the records section. Each record is shown as an entry that is displayed by its title. If you click or tap on the record title, the record will expand to show the record contents (fields) and provide options for deleting, cloning or editing the record contents.

This way of presenting the records is called an accordion display. Below you can see how it expands after the Facebook entry has been selected.

record-expanded

The expanded Facebook record has three fields: url, login and password.

record-expanded

You can copy the field values to the clipboard so that they can be pasted into login forms.

Note that the copy works for passwords whether the password is visible or not.

record-expanded

You can also click or tap on the title of the opened record to close it.

Each of the record management options is discussed in more detail in the Functions section.

Status Section

Below the records section, at the bottom, is the status section where ephemeral status messages are displayed. The messages disappear after about 1.5 seconds but the duration is controlled by a preference that you can set. See the Preferences section for more information.

The status messages are used to provide activity feedback like showing how many bytes were copied to a clipboard when a copy button is clicked or tapped as shown in the example below.

status-message

The following sections will go over the basic menu functions that PAM provides.

In a nutshell they are:

  1. Display information About the application
  2. Create New Record
  3. Edit Record
  4. Delete Record
  5. Clone Record
  6. Clear Records
  7. Save Records
  8. Load Records
  9. Help.

Each function will be discussed in a separate subsection below.

Note that Preferences were not included because they have their own top level section in this document.

About

click or tap on the About menu entry to get information about PAM. You can even add custom HTML through the preferences that is stored for each PAM file.

Here is a screen shot of what you would normally see with no customization. Of course details will vary, like the Commit, Branch or Version fields.

about

Here is the About dialogue with a simple custom message that uses bootstrap formatting classes.

about-custom

Custom messages are defined in the Custom About field in the Preferences as shown below. You can used plain HTML or bootstrap 5 classes (as shown in this example).

about-custom-pref

The motivation for allowing custom messages is that someone might want to share a PAM file or describe how the records are related. The custom message would allow the person to provide their imprimatur on the collection.

Create New Record

Before reading this section, please make sure that you are familiar with the ideas covered in the Topics, Fields and Password Fields sections.

Creating a new record is a very common activity in PAM so I tried to make it as easy as possible.

There are three different methods you can use to create new records:

  1. A record can be created in the application by clicking or tapping the New Record menu option,
  2. A record can be created in the application by cloning an existing record or
  3. A record can be created outside of the application by editing a JSON record file.

Each method is discussed in detail in the following subsections.

Method 1: Menu Approach

The first method, creating the record by clicking or tapping the New Record menu option in the application, is probably the best way to create the first new record for a topic family. This is also known as the menu approach and is shown below.

new-rec

To show how it works, we will create a recipe record using ingredients and instruction fields. But first we need to define them as default textarea fields in the Preferences dialogue. So the available records look like this.

default

To create a new record using the menu approach click or tap on the "New Record" option from the menu.

new-record

That will popup a dialogue that looks like this.

new-record

You can now type in the record title.

new-record

From there you click or tap on the "New Field" pulldown to select and create the first record field. Don’t worry if you select the wrong one, they are easy to delete.

Here is where you select ingredients for the first field.

new-record-field-1-select

Populate it by typing into the textarea box.

new-record-field-1

Now do the same thing to create an instructions field.

new-record-field-2

One interesting thing to understand is that you can change the order of the fields by dragging them up or down. To do that select the field title at the top of the box (fieldset) and move it. This can also be done when editing the record.

Here is what it looks like when I dragged the instructions field up.

new-record-drag

I then dragged instructions field back down because it should appear after ingredients field.

When you are finished click or tap on the "Save" button to save it and you will see it show up as a new record in the records part of the screen.

new-record-done

You can click or tap on the record to expand it and see the fields you just defined.

new-record-done-expand

Method 2: Clone Approach

The second method, creating a record by cloning an existing record, is useful when you want to use the same fields as the existing record. It is a great way to guarantee uniformity. Although if the number of fields is small using the first method is also fine. Here is what the clone option looks like.

clone-rec

Cloning a record is simple. Just expand a record and click or tap on the clone button and an edit dialogue pops up.

Using the record that was created in the previous section here is what happens when you click or tap the "Clone" button.

clone-record-popup

The clone operation created a new record with a slightly modified title Ice Cream Sundae Clone because the record title must be unique and the same fields as the original record.

At this point you would typically change the title and field values but for this demonstration will not do anything. PAM makes sure that the title is unique so it can be saved.

Click or tap the "Save" button and you will see this.

clone-records-1

PAM still remembers that you had the original record open. Just below it you will see the new cloned record.

The reason that the original record is left open is so that it is easy to continue clicking or tapping the "Clone" button to create more records.

In this case we only care about one record so you can click or tap on the new record to expand it.

clone-records-1

Method 3: JSON Approach

The third method, creating a record by editing a JSON record file, is most useful if you are interested in creating records programmatically (perhaps a subset of accounts that shared with a small group of users that is automatically generated from a database). The example records and recipes example files that are available in the Load dialogue are a great place to start.

This approach does not have any screenshots because it deals with PAM internals and may change from time to time. Instead a set of instructions is provided that should allows you to figure it out pretty easily.

  1. Create one record using the menu approach or use one the examples from the Load dialogue.
  2. Save the record to a file without a password. Normally this is a very bad idea because it could expose your data to a hacker so take precautions to protect the file.
  3. Look at the records section of the file and use that as a template to create more records.
  4. When you have finished adding the new records into the file, save the changes and then re-load the file in PAM.
  5. Then save it again with a password.

The reason that this has to be done without a password is because I have not yet written a command line utility to encrypt/decrypt the files. It should be straightforward to do because it uses the standard "AWS_256-CBC" algorithm.

Click here to see an example javascript file

Beware! That the format of this record may change. This is just an example that shows how simple the format is.

{
  "meta": {
    "date-saved": "2022-05-01T20:50:29.125Z",
    "format-version": "1.0.0"
  },
  "prefs": {
    "passwordRangeLengthDefault": 20,
    "passwordRangeMinLength": 12,
    "passwordRangeMaxLength": 32,
    "memorablePasswordWordSeparator": "/",
    "memorablePasswordMinWordLength": 2,
    "memorablePasswordMinWords": 3,
    "memorablePasswordMaxWords": 5,
    "memorablePasswordMaxTries": 10000,
    "clearBeforeLoad": true,
    "loadDupStrategy": "ignore"
  },
  "records": [
    {
      "title": "Amazon",
      "fields": [
        {
          "name": "url",
          "type": "url",
          "value": "https://www.amazon.com"
        },
        {
          "name": "username",
          "type": "text",
          "value": "pbrain22@protonmail.com"
        },
        {
          "name": "password",
          "type": "password",
          "value": "hr5Hn9pqm3u.VqMiALfdN-\""
        },
        {
          "name": "note",
          "type": "textarea",
          "value": "Lorem ipsum dolor sit amet, consectetur adipiscing elit.\nCras sodales elit in metus tempus, ut semper magna finibus.\nDonec aliquam elementum velit quis pharetra.\nPellentesque accumsan neque ut massa elementum mollis.\nNulla eget pellentesque est."
        }
      ]
    },
    {
      "title": "Email pbrain22@protonmail.com",
      "fields": [
        {
          "name": "url",
          "type": "url",
          "value": "https://mail.protonmail.com/inbox"
        },
        {
          "name": "login",
          "type": "text",
          "value": "pbrain22"
        },
        {
          "name": "password",
          "type": "password",
          "value": "rHfZ6bihw$g8ra$P4hHD"
        }
      ]
    },
    {
      "title": "Facebook",
      "fields": [
        {
          "name": "url",
          "type": "url",
          "value": "https://facebook.com"
        },
        {
          "name": "login",
          "type": "text",
          "value": "pbrain22@gmail.com"
        },
        {
          "name": "password",
          "type": "password",
          "value": "dOa#DirgJge67okTKtEzp.LSl"
        }
      ]
    },
    {
      "title": "GitHub",
      "fields": [
        {
          "name": "url",
          "type": "url",
          "value": "https://github.com"
        },
        {
          "name": "login",
          "type": "text",
          "value": "pbrain22"
        },
        {
          "name": "password",
          "type": "password",
          "value": "Aq7GdcOmYWVkyHEWEk6fBeJzm"
        }
      ]
    },
    {
      "title": "Google",
      "fields": [
        {
          "name": "url",
          "type": "url",
          "value": "https://google.com"
        },
        {
          "name": "login",
          "type": "text",
          "value": "pbrain22@gmail.com"
        },
        {
          "name": "password",
          "type": "password",
          "value": "NIJMeb8OfXEfshOG$db!"
        },
        {
          "name": "note",
          "type": "textarea",
          "value": "This is my primary email address.\nsecurity question:\n> what is a photon? gauge-boson"
        }
      ]
    },
    {
      "title": "Netflix",
      "fields": [
        {
          "name": "url",
          "type": "url",
          "value": "http://netflix.com"
        },
        {
          "name": "login",
          "type": "text",
          "value": "pbrain22@gmail.com"
        },
        {
          "name": "password",
          "type": "password",
          "value": "cGwJ$NPQ4SsI#haEsFRD"
        }
      ]
    },
    {
      "title": "StackExchange (StackOverflow)",
      "fields": [
        {
          "name": "url",
          "type": "url",
          "value": "https://stackoverflow.com"
        },
        {
          "name": "login",
          "type": "text",
          "value": "pbrain22@gmail.com"
        },
        {
          "name": "password",
          "type": "password",
          "value": "FpnzQcuq0nk/PxlMdYJ_itnK"
        }
      ]
    }
  ]
}

Edit Record

To edit a record, select it from the records list and click or tap on the "Edit" button to popup the edit dialogue which is exactly the same as the dialogue used to create a new record.

In fact, it is implemented using the same code so you can use the instructions from the Create New Record section to understand how to change or add new fields.

Delete Record

To delete a record, select it from the records list and click or tap on the "Delete" button.

Beware!!! PAM trusts you!!

PAM will not ask you if you really want to delete the record. It will just go ahead and delete it without fanfare so be careful.

Clone Record

To clone a record, select it from the records list and click or tap on the "Clone" button. This will create a new record that you can edit.

The clone operation is described in detail in the Create New Record section under the Method 2: Clone Approach subsection.

Clear Records

Clear all of the records currently defined.

This is normally done automatically when a new file is loaded but could be useful if you want to enter new a set of records from scratch using the currently defined fields. Of course, you could simply delete all of the records manually but this is simpler.

To clear all records choose the  Clear Records option from the menu. See the Menu section for screenshots.

This option will ask you to confirm.

Save File

To save records and preferences to a file by choose the  Save File option from the menu. See the Menu section for screenshots.

This is the save file dialogue.

file-save

If you want the records to be encrypted, enter or generate a password as described in Password Generator section.

If you want to copy the records to the clipboard enter a dot "." as the filename.

Make sure that you do not forget this password. It is the master password this is used to unlock all of the records and PAM does not keep track of it. That means that if the password is lost, PAM cannot recover the data it is lost forever.

More details about the encryption algorithm used can be found in Reason 6: Secure Context Encryption.

Note that if you do not enter a password, the output will be plain javascript that can be read by anyone.

Plain javascript is NOT secure.

If you have records with passwords ALWAYS use a password unless you understand the consequences. For example, saving the data without a password can sometimes be convenient because it allows you to see how the PAM data is organized which can aid automation.

Load File

To load records and preferences from a file by choose the  Load File option from the menu. See the Menu section for screenshots.

This is the load file dialogue.

file-load

If the file was saved with a password, you must enter that password or the file will prompt for the password when loading.

Load Example Records

If you wish to load the example records file, click or tap on the Load Example Records button (#1) to load the following example records that can be used to get you started.

file-load-example-records

Load Example Recipe

If you wish to load the example recipes file, click or tap on the Load Example Recipes button (#2) and PAM will load this.

ice-cream-sundae-example

Load Records from URL

Click or tap on the Load Records from URL button (#3) to load a file from the web.

This is typically used when a PAM records file is shared because no changes can be made.

Paste Records from Clipboard

Click or tap on the Paste Records from Clipboard button (#4) to paste records from the clipboard.

This is typically used when records are copies to the clipboard from a save operation or manually after editing.

Get Help

To get this help message, choose the "Help" option from the menu.

If you find a bug or want to request a change or submit an improvement, go to the Metadata section at the top of this help and click or tap on the project link.

Preferences

Preferences allow you to customized the behavior of the app. The defaults are set so that most people will never have to change anything.

The preferences dialogue is a big one. It is broken into 4 sections to make it easier to understand:

  1. Search - preferences that control searches.
  2. Passwords - preferences that control password creation and length.
  3. Miscellaneous - preferences for other stuff.
  4. Record Fields - the definitions of the available fields.

Each preference is discussed in more detail in the subsections below.

Search Preferences

pam-prefs-search

These preferences control search options. See the Search section for an example.

Case Insensitive Searches

If enabled, all searches are case insensitive, otherwise they are case sensitive.

The default is enabled.

Search Record Titles

If enabled, all searches look at the record titles, otherwise they do not.

The default is enabled.

Search Record Field Names

If enabled, all searches look at the record field names, otherwise they do not.

The default is not enabled.

You would want to enable this you wanted to see records that contained a specific field.

Search Record Field Values

If enabled, all searches look at the record field values, otherwise they do not.

The default is not enabled.

You would want to enable this you wanted to see records that contained a specific field value like an obsolete email or really old password.

Password Preferences

pam-prefs-password

These preferences control automatic password creation.

For more information about passwords see Password Fields

Minimum Password Length

Defines the minimum length of generated cryptic and memorable passwords.

The default is 12.

I would recommend not making it shorter than the default unless a website specifically demands it because shorter passwords are easier to crack.

Maximum Password Length

Defines the minimum length of generated cryptic and memorable passwords.

The default is 32.

I would recommend making it longer than the default if you can but many websites have an upper bound for the length of password. The chosen default seems to work for most of them.

Memorable Password Min Word Length

Defines the minimum size of a word in a generated memorable password. > It has no affect on cryptic passwords.

The default is 2.

If you do not want short words like 'as' or 'it', then make this longer. I would not recommend making it shorter.

Memorable Password Word Separator

The string used to separate the words in a generated memorable password.

It has no affect on cryptic passwords.

The default is a single character: '/'.

If you want to change the character, add any string that you like. It can be multiple characters. Other reasonable choices might be ':' or '.' or '@@' or whatever you like. It is best not to use letters.

Memorable Password Min Words

The minimum number of words in a generated memorable password.

It has no affect on cryptic passwords.

The default is 3.

Memorable Password Max Tries

The maximum number of attempts to generate a memorable password that meets the specified criteria from the other password preferences.

It has no affect on cryptic passwords.

The default is 10000.

There is normally no need to ever change this but, if you change it and make it too small, PAM will report errors if it fails to generate passwords after the maximum number of tries.

Memorable Password Prefix

The prefix to add to all generated memorable passwords.

The default is '' (empty string).

You might want to add a prefix or suffix to make sure that the generated passwords meet the requirements of websites that require upper case letter, digits and special characters.

For example, you might specify something like 'A1!!/' to meet the criteria which might create passwords like 'A1!!/html/wishes/combined' or 'A1!!/rebates/restructuring/jamaica'.

Memorable Password Suffix

The suffix to add to all generated memorable passwords.

The default is '' (empty string).

You might want to add a prefix or suffix to make sure that the generated passwords meet the requirements of websites that require upper case letter, digits and special characters.

For example, you might specify something like '/A1!!' to meet the criteria which might create passwords like 'html/wishes/combined/A1!!' or 'rebates/restructuring/jamaica/A1!!'.

Miscellaneous Preferences

pam-prefs-miscellaneous

These are the preferences that didn’t fall into the other categories.

Log Status to the Console

Log status messages to the console as well as the screen to aid debugging.

The default is false which says do not log status messages to the console.

You might want to enable console logging if you are debugging a problem and are working in a browser that supports debugging.

Clear Records On Load

Clear all records before loading records from a file.

The default is true which says to clear the records before a loading new records from a file.

If you set this to false, another option titled Load Duplicate Record Strategy will appear that is not normally visible to ask you with strategy you want to used for conflicts.

You might set this preference to false if you want to to merge sets of records from different files.

Enable Printing

Click this to add the Print option to the menu.

This is what the enable printing preference looks like in the preferences dialogue.

pam-prefs-enable-printing-check

Once it is enabled, the Print option will appear at the bottom of the menu as shown below.

pam-prefs-enable-printing-menu

When you click on Print, PAM will print the records with the passwords visible. This is what it looks like for the example records.

pam-prefs-enable-printing-example

This capability is useful if you want a paper copy of your records but it is a security risk. If you choose to enable this option, make sure that the paper copy is stored securely.

Disable this option (the default) if you intend to share PAM records with multiple users from a read-only URL.

Load Duplicate Record Strategy

This preference is not visible unless the Clear Records On Load preference is false.

It presents three strategies for handling duplicate records during a load operation: allow, ignore, replace.

The allow strategy allows duplicate records to exist by cloning them. For example if a record with the title Google exists in the records and in the file being loaded, the record from the file would be renamed to Google Clone.

The ignore strategy ignores the duplicate record that is being loaded. If there is a conflict it prefers the one already present.

The replace strategy ignores the duplicate record that already exists. If there is a conflict it prefers the record being loaded.

Clone Field Values when Cloning Records

This preference specifies that all data is kept when cloning a record.

Remember that cloning a record is very simple and powerful way to create new records with the same fields but you have to delete the existing values before entering new ones which is very simple.

The default is false which says to keep the field values when cloning.

Set this preference if you want to avoid deleting the fields manually.

Require Record Fields

This determines whether a record can be created with no fields.

If it is true, then a new record must have a least one field defined.

The default is false which means that records can be created with no fields so that records.

Enable Editable Field Name

This preference defines whether or not the user can change a field name on a per record basis.

Setting this preference is not recommended because the presence of the name input can be confusing for users, a better approach is to simply add a new field to the default fields in the preference section as described in the Fields section.

Not Enabled

This is what it looks likes when it is unchecked (false).

false

false

When this is not enabled, the user can only choose record fields from the Record Fields section of the preferences. See the Record Fields section for more details.

Enabled

This is what it looks likes when it is checked (true).

false

true

The user can replace the default field name (in this case name) with whatever they want, perhaps something like full name or first name or last name. The value field is where the name is actually entered.

filePass Cache Strategy

This defines the browser cache strategy for the file password. The options are none, prefs, local and session.

The none option means that the file password is never stored. The file password is not remembered for the file load and save operations. Each time you load or save a file you must re-enter it.

The global option means that the file password is stored in a global window session variable. The file password is remembered for the file load and save operations. It is remembered until the browser tab is closed.

The local option means that the file password is stored in localStorage. The file password is remembered for the file load and save operations. It is remembered until it is explicitly reset.

The session option means that the file password is stored in sessionStorage. The file password is remembered for the file load and save operations. It is remembered until the browser tab is closed.

Custom About

Customized HTML that is added to the about page. It can be used in cases where the field records have been customized to provide an explanation or link to internal documentation.

Its use is described in the About section.

Record Fields

These are the default record fields that are used when creating or editing record fields. They can be can be changed.

See the Fields section for more information about record fields.

At the top of the section there is add icon that is used to create a new record field.

Each default record field has a name, a type (from a pulldown menu) and a delete button (trash) that you click to delete the record field.

The record field names must be unique but you can modify them. They are stored with the each record file individually.

This is what the default records filed preference dialogue looks like.

default

Saving Preferences

You must scroll to the bottom of the dialogue and click on the "Save" button at the end to save changes. If you do not, any changes you made will be lost.

Security Considerations

PAM, like all web applications, has security challenges. By fully disclosing them here you can understand the challenges and improve your ability to protect your record data.

MITM

MITM refers to Monster In The Middle attacks or, historically, Man In The Middle attacks. It an attack where a hostile eavesdropper inserts themselves in the communications stream between a client and a server to capture or alter the communications for nefarious purposes like stealing credentials.

PAM is not susceptible to this attack because it does not communicate with a server. That is because it is a single page web application that is downloaded and run within your browser. All data is local. Nothing is ever transferred over the internet for an eavesdropper to capture.

Third Party Web Site Security

Third party web site security can be a major source of cybersecurity vulnerabilities because clients cannot know how well such cybersecurity vulnerabilities are mitigated unless that site publishes a detailed report, on a periodic basis, of how often they were attacked successfully and how many attacks they have successfully fended off.

Sadly, most companies do not provide that information. If you are using a password manager or any other service that uses a server, you might want to consider asking them how vulnerable they are to cyberattacks. At a minimum, you will want to understand what is done to protect your data from insider attacks where an employee steals the data.

Sometimes you can get information about the security of a site by looking at Common Vulnerability and Exposures (CVE) reports. See https://www.cve.org/ for more information.

Poor reporting of third party web site cybersecurity vulnerabilities and exposures was one thing that motivated me to write PAM.

Because PAM does not send the data to a server, it is not vulnerable to how cybersecurity is managed on the server by a third party.

You can verify that PAM is not sending data out by monitoring outbound traffic from your system. PAM never sends any outbound data.

PAM encryption and decryption operations are provided by and run inside the secure context of the browser. This is the same secure context used for accessing sites securely for transactions, like your bank. In practice this means that you must access PAM from an HTTPS site.

The safety and security of secure context operations is taken very seriously by the internet standards organization and the organizations that develop the major browsers.

You can read more about secure contexts here and in Reason 6: Secure Context Encryption.

Site Reliability

Although it is not an attack vector per se, site reliability is another consideration when choosing a web application because a distributed denial of service (DDoS) attack on the site or a power failure at the site could make it unusable.

Fortunately, most modern web applications are built using commercial cloud software as a service (SaaS) and infrastructure as a service (IaaS) products from vendors like AWS, Azure and GCP so they tend to be very reliable but it is still something to be aware of because if the site or the gateway to the site goes down so does the web application.

PAM, is hosted and served from github.io which also appears to be very reliable but if you are concerned, you can host it wherever you like. Also PAM does not do any backend server communication (as mentioned earlier) so it will like continue to run even if the site goes down temporarily because, once it is loaded, it will stay resident until you close the browser tab.

Another thing to consider is where you store your PAM record file(s). I use iCloud which is also quite reliable and allows access to iCloud files directly from my computers, mobile devices and tablets.

Just make sure that whichever infrastructure as a service (IaaS) offering you choose it is reliable as well because you don’t want to lose access to your file because the IaaS service is not available.

Of course you could simply load and save the data to a local file but that might restrict access to it from other devices (like mobile phones or tables) and you would have to be very diligent about keeping it backed up.

Over the Shoulder Surfing Attack

The user enters the record data in decrypted form, so it may be vulnerable to over the shoulder surfing attacks where someone or something (like a camera) watches or films the user typing or opening a record and then clicking or tapping on a password field to display the password in plaintext which could allow that information to be stolen.

This vulnerability can be mitigated by being aware of your surroundings to make sure you are not being watched or filmed.

This is different and easier to mitigate than key-logging and screen recording as discussed in the next subsection.

Malware: Key Logging and Screen Recording

If malware that takes screenshots or does key logging has been installed on your computer, phone or tablet, you are in trouble for a variety of reasons. It means that an attacker can see what you are doing and capture what you are typing.

The best way to mitigate these forms of attacks is to keep your system up to date by installing security patches and by using some sort of security tool or tools to protect your system or, at the very least, recognize the infection.

Malware: Clipboard Attack

Yet another type of vulnerability is the clipboard attack if/when data is copied to the clipboard for cut and paste operations. This vulnerability exists because the clipboard is a global resource that can be accessed by other, independent applications.

Clipboard attacks can be mitigated by making sure that your computer does not have malware installed or by not copying to the clipboard. Although it is probably impractical to not use the clipboard at all so, if you do use the clipboard, make sure that you always reset it after any copy/paste operation to minimize any chances that it will be captured by malware or observed by an attacker. You can reset it by simply selection a single letter or word and copying it.

Another, perhaps better, way to mitigate the clipboard vulnerability might be to eliminate the need for the clipboard by modifying PAM to automatically login in for you based on record data using an HTTP POST operation but that is not currently available.

Note that I say might here, because I do not know how secure POST operations are.

Unattended Browser

If you leave the browser unattended without locking your screen after you have loaded your record data, someone can sit down and see the records because they are impersonating you after you have logged in.

The best way to mitigate this attack is to always lock your screen when you leave the computer unattended.

Website Spoofing

Web site spoofing could be used to direct you to a website that could be used to steal your information using a look alike web application.

To mitigate that make sure that you accessing the PAM from a known, trusted site.

If you are concerned about this, you can always download, build and run PAM from your own trusted site.

Dictionary and Brute Force Password Attacks

In general a brute force attack is any attack that uses trial and error to crack passwords.

A dictionary attack is a brute force password attack that tries every password in a dictionary to break decrypt sensitive data.

Both attacks are very effective in cases where the attacker has the ability to try many passwords without being locked out and where the password is short.

PAM is vulnerable to dictionary attacks and brute force atttacks because it can be run locally where the attacker can setup an automatic system to try to decrypt the file using the set of available passwords.

Sites that require passwords for authentication can mitigate this type of attack by limiting the number of login attempts allowed.

PAM can also mitigate these types of attacks but it cannot do so automatically because the attacker has access to the source code. Instead you can mitigate these attacks by using strong (high entropy) passwords.

To give you some feel for just how effective this approach is, consider a simple example where we have a password composed of say 20 pseudo-random upper case letters (26), lower case letters (26), digits (10) and 2 special characters.

Thus for 20 characters, there are 6420 or 1,329,227,995,784,915,872,903,807,060,280,344,576 (~1.3 undecillion) possible passwords which is which is one heck of a lot possibilities!

If an attacker were to try to crack such a password using a super powerful computer that could perform 1 billion tests per second (close to the limit of todays technology), it would take something on the order of about a sextillion (1021) years to crack which means that your data is pretty safe if you use such a password.

On the other hand if you use a simple, six character password like secret it would take about about a minute so don’t do that.

Ideas for generating strong password are discussed in the next section.

Protecting Yourself

In summary, security can never be fully guaranteed, the best way to protect your data is to follow commonly recommended security practices:

  1. Keep all of your security patches up to date.
  2. Keep malware off of your systems.
  3. Make sure that you are not observed.
  4. Never share sensitive information (like passwords).
  5. Backup your data.
  6. Use a strong password for encrypting your files.
    1. It should be at least 20 characters.
    2. It should not contain personally identifiable information like dates.
    3. It should be memorable and fairly easy to type.
    4. I suggest using a memorable password of length 30 or more that contains 3 to 5 words with a custom prefix and suffix. Perhaps something with a structure like this: A1/jeans/chosen/since/tuition?!! (do NOT use this specific password!).
  7. Make sure that the website URL is what you expect.

Multi-Factor Authentication

Several folks have asked me why Multi-Factor Authentication (MFA) was not included in PAM to provide and additional layer of security.

In general the MFA approach assumes that the users identity must be checked and validated (authentication) so that the site offering the services knows that it is dealing with the valid user not an impersonator which is a great thing but it is not necessary for PAM because PAM has no site.

Instead PAM is a single page web application with no backend processing, which, once it is loaded, makes it more like a local word processor that is tailored to managing customized records in local files so any additional communication over the internet represents a risk as does storing any user information. Everything is done inside the browser in a secure context.

No outbound information is ever sent to the internet unless the user specifically requests it via the "Load File" and "Save File" operations while using cloud storage but at that point all data is encrypted both at the file level and as the HTTPS transport level which is required for the browser secure context which, in turn, is required by PAM to function which is pretty safe if you protect your data with a strong password.

You can verify that PAM is functioning securely by monitoring outbound internet traffic. You should never see any outbound traffic from PAM that is not related to the file load and save operations.

For all of the above reasons, I felt the MFA would not improve security and, hence, was not needed.

Usage Examples

The examples in this section talk about how to use this app under different scenarios.

Personal Account Records

This is the most common usage. It is where personal account records are stored so that you have a permanent, encrypted record of all of your passwords.

Create Record File

To create a file with a single record follow these steps:

  1. Navigate to the app: https://jlinoff.github.io/pam/www/.
  2. Select the "New Record" option from the menu in the upper right hand corner.
  3. When the new record dialogue pops up, enter the account name as the title, an example might be Google email.
  4. Add fields like url, login and password and set their values.
  5. Save the record.
  6. At this point it will appear as your first record on the display.
  7. Now save it to a file by selecting Save File from the menu.
  8. Enter the file name, perhaps something like "mystuff.pam" or "joe.pam" if your name is Joe or "account.pam".
  9. Enter a password.
    1. This is the password that you need to access all of the records in the file.
    2. The password is not stored so make sure that you keep track of it somewhere because if it is lost, the records cannot be retrieved.

At this point your data is stored. You can add as many additional records as you want or change existing records. As long as you save them, they will be available to you.

Use Record Data to Log into a Site

To use the data to log into a site.

  1. Navigate to the app as described above.
  2. Click or tap on the record that contains the information.
  3. Click or tap on the url link so that the site opens up in a different tab.
  4. Enter the login name or email by clicking or tapping on the clipboard icon next to the login name and paste into the site.
  5. Enter the password by clicking or tapping on the clipboard icon next to the password and paste into the site.
    1. You do not need to make the password visible to do this.
    2. It picks up the correct password even when it is hidden.

Edit an Existing Record

To edit an existing record.

  1. Navigate to the app as described above.
  2. Click or tap on the record that contains the information.
  3. Click or tap on the edit icon.
  4. Edit the record to make the necessary changes to the fields or title.
  5. Save the record.
  6. Make sure to save the file when you are done.

Delete an Existing Record

To delete an existing record.

  1. Navigate to the app as described above.
  2. Click or tap on the record that contains the information.
  3. Click or tap on the delete icon.
  4. Make sure to save the file when you are done.

Clone an Existing Record

This is a really powerful operation that allows you to quickly create records with the same fields.

To clone a record.

  1. Navigate to the app as described above.
  2. Click or tap on the record that contains the information.
  3. Click or tap on the edit icon.
  4. Edit the record to update the fields.
  5. Save the record.
  6. Make sure to save the file when you are done.

If you want to disable the copying of field data turn off the Clone Field Values when Cloning Records preference. That avoids having to delete each old field value before typing in the new field value.

Share Credentials for a Small Group

This scenario assumes that a small group of trusted people wants to share a common file of account records with credentials that can only be decrypted using a single shared password that is only known to the group.

This might be suitable for a small group that requires administrative access to a small number of accounts.

Because it involves sharing a password, this approach may be too insecure for some.

If this approach is adopted, it would be wise to change the shared password frequently, to audit all access to the shared file as well as audit all access to the accounts. Also, since the shared file must be on a mounted volume that can be seen by the input file dialogue, access to the mount and, by extension, to the file can also be restricted.

Here are the high level steps necessary to share a PAM file.

  1. Create the mounted volume where the file will be located.
  2. Create the pam file and populate it with the shared records.
  3. Save the file to the mounted volume with a password.
  4. Communicate the location of the file and the password to the members of the group in a secure way.

Another approach is to create the encrypted PAM file and store it on a publicly accessible web site. Users can then use option #3 in Load File dialogue to load it.

Recipes

This is a bit of contrived example because you could easily keep all of your recipes with your other personal account data but it might be useful if you want to keep them separated.

The key notion here is the idea of creating two new fields in the preference dialogue: ingredients and instructions, and then use them when you enter recipes.

Here are the high level steps necessary to get the fields defined.

  1. Open the preferences dialogue from the menu.
  2. Add the new fields by clicking or tapping on the trash icon in the "Record Fields" in the preferences section.
    1. "ingredients" of type textarea.
    2. "instructions" of type textarea.
  3. Delete all of the other record fields defined in the preferences by clicking or tapping on the trash icon because there is no need for them.

To search by an ingredient, set the Search Record Field Values preference to true by clicking or tapping on it and then saving it.

Books

This is another somewhat of contrived example because you could easily keep all of your book reviews with your other personal account data but it might be useful if you want to keep them separated.

For my book reviews, I enter the book title as the record title and added the following fields using the methodology described in the recipes section above.

Note that I only add records for books that have been read.

name type description
author textarea there maybe multiple authors
date-read text when it was read
thoughts textarea my thoughts about the book

To search by author, set the Search Record Field Values preference to true by clicking or tapping on it and then saving it.

Developer Notes

These are things that developers might be interested in.

It was built using pure javascript and relies on the browser secure context to provide encryption and decryption.

It uses bootstrap-5 to make it work better in mobile browsers.

It uses pylenium to test the web app which means the github actions file main.yml is pretty interesting because it demonstrates to how to build a complete web test environment using python on an Ubuntu:20.04 VM with a local web server.

Not only that but I wrote my own little, lightweight javascript library to provide a limited functional interface to make coding HTML DOM constructs easier. See the www/js/lib.js source code module.

License

PAM is free and open-source (FOSS) software that licensed under the MIT Licensing terms.

Although not required, I would appreciate attribution if you decide to copy and use the source code.

MIT License Terms

Build PAM

Here are the steps to build PAM.

  1. git clone https://github.com/jlinoff/pam.git
  2. make or make init
  3. make run

Create Favicon

I could not automate this process because I used a web service.

  1. Created an image using draw.io.
  2. Uploaded the image to https://favicon.io/favicon-converter/. It converted the image automatically when the Download button was clicked.
  3. Per the instructions on the site, then downloaded the following files into pam/www
  4. Also per the instructions on the site, added the link tags to pam/www/index.html.
  5. Edited the newly added link tags in pam/www/index.html to make them relative by prepending a dot to the href path) like this.
<link rel="apple-touch-icon" sizes="180x180" href="./apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="./favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="./favicon-16x16.png">
<link rel="manifest" href="./site.webmanifest">
  1. Edited the link tags in pam/www/site.webmanifest to make them relative as well by prepending a dot to the src path like this. Note that the original was not not formatted, I formatted here to make it easier to read.
  "name": "",
  "short_name": "",
  "icons": [
    {
      "src": "./android-chrome-192x192.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "./android-chrome-512x512.png",
      "sizes": "512x512",
      "type": "image/png"
    }
  ],
  "theme_color": "#ffffff",
  "background_color": "#ffffff",
  "display": "standalone"
}

Test PAM

Here are the steps to test PAM.

  1. make test

The test infrastructure uses python and pylenium to automate user interactions.

Release PAM

Note that PAM will not work unless it is released to a secure (HTTPS) server because it requires a secure context.

Note that installing it on local server (localhost or 127.0.0.1) is considered secure which is convenient for personal use.

Here are the steps.

  1. Update the VERSION file using semantic versioning.
  2. Run make to propagate the new version and update README.md
  3. Run make web to create pam-www.tar which contains the app in pam/www.
  4. Untar the pam-www.tar on your site.

This pre-supposes that you have cloned the pam project from github.

History

This is one of the several times that I have written a password manager from scratch over the past twenty years and it is intended to be the last. Because this version while it is far from perfect, is good enough for my needs and should provide a decent start for someone who wants to improve it.

If you are interested in the evolution of this project read on.

Below are three previous implementations that are still around followed by a brief chronology of how things progressed over the years.

passman

Circa 2010
Project https://joelinoff.com/blog/?page_id=1025
Webapp https://projects.joelinoff.com/passman/passman-v0.7/

This is the oldest surviving effort. It is an early incarnation written in pure javascript that uses a table paradigm for presenting the data. The UI and the implementation are quite complex.

qspm

Circa 2018
Project https://github.com/eSentire/qspm
Webapp https://esentire.github.io/qspm/

This is the older effort that was implemented using Rust and javascript and was funded by my employer at that time (eSentire, Inc.) for a hack week project. The UI and the implementation are quite complex.

The acronym stands for Quantum Safe Password Manager. An ambitious name to say the least.

myvault

Circa 2020
Project https://github.com/jlinoff/myvault
Webapp https://jlinoff.github.io/myvault
Help https://jlinoff.github.io/myvault/help

This is the precursor to pam. It was implemented using Rust and javascript. I used it for a several of years.

It has poor implementations of the record create and edit dialogues and a poor implementation of the password generator dialogue.

Other than that it was okay.

pam

Circa 2022
Project https://github.com/jlinoff/pam
Webapp https://jlinoff.github.io/pam/www/
Help https://jlinoff.github.io/pam/www/help/

This is the latest incarnation and it is pure javascript. It fixes some of the problems seen in the earlier attempts and it leverages bootstrap-5 to make it work better in mobile browsers. The implementation is a bit simpler but like all of the other attempts there is still plenty of room for improvement.

The acronym stands for Personal Accounts Manager or Password Manager or whatever. It doesn’t really matter. I just wanted something short and easy to remember.

Chronology

I first wrote a password manager in the early 2000’s in javascript. In those days I had to write my own uncertified implementations of the encryption algorithms like AES-256-CBC and AES-256-GCM and DES3 but that was perfectly okay because, back then, my day job involved a lot of security stuff like designing hardware and software (in C++) to implement certified algorithms.

As time went on, I would continue to re-implement password managers as a hobby to learn new skills and refresh old ones. That pretty quickly got me into javascript, python, docker, golang and, a few years ago, to rust. It has been a fun journey and I learned a great deal.

By the time, I got around to writing PAM, I was using the prototype for a lot more than password management (mostly because I could enter records from my phone). It was a useful idiom for record management in general which is where things are today.

You will see that I dropped Rust in the latest incarnation but that is not because I don’t think Rust is suitable or wonderful. Rust is most definitely suitable and wonderful. I dropped it because I did not need it. The secure context had everything I needed.

In a perfect world, I would have done this in emacs org-mode (yes, I am one of those) but I was never able to get remote access from multiple devices working as well as I liked so I stuck with javascript.

I sincerely hope that there is something here that others can learn from this.

I have really enjoyed playing around with password management over the years. The journey has been great fun.

Enjoy.